我一直在研究Haskell中的Monoid及其用途,这使我对Monoid的基础有了相当好的理解。在这篇博客文章中介绍的其中一件事就是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用法,因为我很新手)。
-- 编辑 --
在下面的评论中,Paul Johnson建议将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,因为我不知道a的mempty值是什么。我该如何概括这个问题?