在 Haskell 中使用 Maybe 编写最大幺半群
我一直在研究 Haskell monoids 及其用途,这让我对幺半群的基础知识有了相当好的理解。博客文章中介绍的内容之一是任何幺半群,其用法如下:
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
但我不清楚如何在不知道 a 的 mempty 值应该是什么的情况下表达 mempty 。我该如何概括这一点?
I've been going through Haskell monoids and their uses, which has given me a fairly good understanding of the basics of monoids. One of the things introduced in the blog post is the Any monoid, and it's usage like the following:
foldMap (Any . (== 1)) tree
foldMap (All . (> 1)) [1,2,3]
In a similar vein, I've been trying to construct a Maximum monoid and have come up with the following:
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
I could construct a Maximum monoid for a specific type - say Num for example, quite easily, but want it to be useful for anything (with the obvious requirement that the anything is an instance of Ord).
At this point my code compiles, but that's about it. If I try to run it I get this:
> 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)
I'm not sure if this is because I'm calling it wrong, or because my monoid is incorrect, or both. I'd appreciate any guidance on where I'm going wrong (both in terms of logic errors and non-idiomatic Haskell usage, as I'm very new to the language).
-- EDIT --
Paul Johnson, in a comment below, suggested leaving Maybe out. My first attempt looks like this:
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
but I'm unclear how to express mempty without knowing what the mempty value of a should be. How could I generalise this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
传递给
foldMap
的函数需要返回一个幺半群,在本例中为Maximum a
类型:The function passed to
foldMap
needs to return a monoid, in this case of typeMaximum a
: