在Haskell中使用Maybe写一个最大Monoid

时间:2011-03-17 19:28:04

标签: haskell monoids

我一直在经历Haskell monoids and their uses,这让我对幺半群的基本知识有了很好的理解。博客文章中介绍的内容之一是Any monoid,它的用法如下:

foldMap (Any . (== 1)) tree
foldMap (All . (> 1)) [1,2,3]

与此类似,我一直试图构建一个最大的幺半群,并提出以下内容:

newtype Maximum a = Maximum { getMaximum :: Maybe a }
        deriving (Eq, Ord, Read, Show)

instance Ord a => Monoid (Maximum a) where
        mempty = Maximum Nothing
        m@(Maximum (Just x)) `mappend` Maximum Nothing = m
        Maximum Nothing `mappend` y = y
        m@(Maximum (Just x)) `mappend` n@(Maximum (Just y))
          | x > y = m
          | otherwise = n

我可以为特定类型构造一个最大幺半群 - 例如Num,很容易,但希望它对任何东西都有用(明显要求任何东西都是Ord的实例)。

此时我的代码编译,但就是这样。如果我尝试运行它,我会得到这个:

> foldMap (Just) [1,2,3]

<interactive>:1:20:
    Ambiguous type variable `a' in the constraints:
      `Num a' arising from the literal `3' at <interactive>:1:20
      `Monoid a' arising from a use of `foldMap' at <interactive>:1:0-21
    Probable fix: add a type signature that fixes these type variable(s)

我不确定这是因为我说错了,还是因为我的幺半群不正确,或者两者兼而有之。我很欣赏任何关于我出错的指导(无论是逻辑错误还是非惯用的Haskell用法,因为我对语言都不熟悉)。

- 编辑 -

保罗约翰逊在下面的评论中建议将Maybe留下。我的第一次尝试看起来像这样:

newtype Minimum a = Minimum { getMinimum :: a }
        deriving (Eq, Ord, Read, Show)

instance Ord a => Monoid (Minimum a) where
        mempty = ??
        m@(Minimum x) `mappend` n@(Minimum y)
          | x < y     = m
          | otherwise = n

但我不清楚如何表达mempty而不知道应该是什么样的mempty值。我怎么能概括这个?

1 个答案:

答案 0 :(得分:12)

传递给foldMap的函数需要返回一个monoid,在这种情况下类型为Maximum a

> foldMap (Maximum . Just) [1,2,3]
Maximum {getMaximum = Just 3}