使用Haskell中的Maybe编写最大Monoid

12

我一直在研究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值是什么。我该如何概括这个问题?


我知道它是如何工作的,但为什么在Maximum类型中要有“Maybe a”?如果你只说“Maximum a”,那么它会简化你的实例。只要“a”是Ord的一个实例,“Maybe a”就是Ord的一个实例,所以你可以只说“Maximum (Maybe Integer)”,它就会做正确的事情。 - Paul Johnson
@Paul Johnson,我理解你不使用Maybe的原因,但我不知道该如何表达。我已经将代码添加到我的问题上方,以使其更易读。 - lukerandall
3
哦,我明白你的问题了。如果你将“Bounded”作为一个限制条件添加进去,那么mempty就可以返回最小值的下界和最大值的上界。否则你是正确的,mempty无法做出正确的操作。这意味着它不是一个单子。 - Paul Johnson
1个回答

13

foldMap函数的参数需要返回一个单子,本例中为Maximum a类型:

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

既然你指出来了,看起来真是显而易见 :) 谢谢你的回答! - lukerandall
2
ala' Maximum foldMap Just [1,2,3] = Just 3 -- 给定Maximum的适当Newtype实例。来自此软件包:http://hackage.haskell.org/package/newtype - Darius Jahandarie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接