将函数转换为可能类型

时间:2013-09-18 00:40:15

标签: haskell fold maybe

我正在尝试将使用foldr函数的最大函数转换为也包含may类型的函数。它最初是:

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.

2 个答案:

答案 0 :(得分:4)

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

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

此外,Learn You A Haskell是一个很好的资源,如果你还没有遇到它!

答案 1 :(得分:4)

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

对于所有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