【问题标题】:Converting Function To Maybe Type将函数转换为 Maybe 类型
【发布时间】:2013-09-18 00:40:15
【问题描述】:

我正在尝试将使用 foldr 函数的最大函数转换为也包含可能类型的函数。原来是:

maximum' :: (Ord a) => [a] -> a  
maximum' = foldr1 (\x acc -> if x > acc then x else acc)

它适用于集合,但不适用于空集合。我想将其转换为使用可能的类型。

我的思考过程是:

mymax :: (Ord a) => [Maybe a] -> Maybe a 
mymax = foldr (\(Just x) (Just b) -> if ((Just x) > (Just b)) then (Just x) else (Just b)) Nothing

当我给它一个空集时,它编译没有错误并且可以工作。但是,当我给它一个带有数字的集合时,它不再起作用了!有人能指出我如何从可能的列表中获得最大功能的正确方向吗?

我真的很想在我的解决方案中使用 foldr 函数......

我现在已经试过了:

mymax :: (Ord a) => [a] ->  Maybe a 
mymax = foldr (\x b -> if x > b then (Just x) else (Just b)) Nothing 

但它不会编译:

    Couldn't match expected type `Maybe b -> Maybe a'
                with actual type `Maybe a0'
    In the return type of a call of `Just'
    Probable cause: `Just' is applied to too many arguments
    In the expression: (Just x)
    In the expression: if x > b then (Just x) else (Just b)
Failed, modules loaded: none.

【问题讨论】:

    标签: haskell fold maybe


    【解决方案1】:

    如果您想在单个foldr 中执行此操作,我们可以利用Ord a => Ord (Maybe a) 的事实,即a 上的任何排序都可以扩展为Maybe a 上的排序。

    我们还有Just x > Nothing,适用于所有x :: Ord a => a。

    mymax :: (Ord a) => [a] ->  Maybe a 
    mymax = foldr (\x b -> let x' = Just x in if x' > b then x' else b) Nothing 
    -- equivalently
    mymax = foldr (\x b -> let x' = Just x in max x' b) Nothing 
    mymax = foldr (\x' b -> max x' b) Nothing . map (\x -> Just x)
    mymax = foldr max Nothing . map Just
    

    如果我们想要做最小值,我们将不得不做一些不同的事情,因为Nothing 是Ord a => Maybe a 类型的下限,这意味着foldr min Nothing . map Just == const Nothing 没有用处。

    mymin :: (Ord a) => [a] -> Maybe a
    mymin = foldr (\x b -> case b of
        Nothing -> Just x
        Just y  -> Just (min x y)
      ) Nothing
    -- which is equivalent to
    mymin = foldr (\x b -> Just $ case b of
        Nothing -> x
        Just y  -> min x y
      ) Nothing
    mymin = foldr (\x b -> Just $ maybe x (min x) b) Nothing
    mymin = foldr (\x -> Just . maybe x (min x)) Nothing
    

    不过,老实说,我认为模式匹配使解决方案更加清晰

    mymax [] = Nothing
    mymax (a:as) = Just $ foldr max a as
    
    mymin [] = Nothing
    mymin (a:as) = Just $ foldr min a as
    

    【讨论】:

    • 我唯一的问题是符号“$”是什么,我尝试用谷歌搜索它,但我得到了很多关于购买 haskell 书籍的结果......
    • @ZAX 也许你应该买一本haskell 书然后:) 开个玩笑,$ 是一个标准的应用程序功能。 f $ x 与 f x 相同。它通常用于消除括号。 Just $ foldr max a as == Just (foldr max a as)。如果没有$,这很快就会变得更加复杂,并且在阅读代码时需要解开更多的括号。例如,尝试将右括号放在语句Just (case b of .....) 中,然后尝试弄清楚如何阅读代码——如何匹配)。 $ 告诉读者“……表达式的其余部分是前一个函数的参数”。
    • 另外,如果您想查找 haskell 运算符,请尝试 hoogle 和 hayoo
    【解决方案2】:

    我认为您实际上希望 mymax 具有 (Ord a) => [a] -> Maybe a 类型。这是一个使用模式匹配和您原来的 maximum' 函数的潜在实现:

    mymax :: (Ord a) => [a] -> Maybe a
    mymax [] = Nothing
    mymax xs = Just (maximum' xs)
    

    另外,Learn You A Haskell 是一个很好的资源,如果您还没有遇到过的话!

    【讨论】:

    • 我真的在尝试使用 foldr 的方式来做这件事,虽然是的,这确实有效
    • @ZAX你更新代码的问题是x的类型是a,b的类型是Maybe a,所以不能比较。
    猜你喜欢
    • 1970-01-01
    • 2021-11-10
    • 2021-07-03
    • 1970-01-01
    • 1970-01-01
    • 2019-08-18
    • 1970-01-01
    • 1970-01-01
    • 2014-05-19
    相关资源
    最近更新 更多