模式匹配中的Monoid mempty

mmh*_*mmh 5 haskell pattern-matching monoids

我试着编写一个maximum类似于中的函数的广义函数Prelude.我的第一个naiv方法看起来像这样:
maximum' :: (F.Foldable a, Ord b) => a b -> Maybe b
maximum' mempty = Nothing
maximum' xs = Just $ F.foldl1 max xs

但是,当我测试它时,Nothing无论输入如何,它总是返回:
> maximum' [1,2,3]
> Nothing

现在我想知道是否有可能获得Monoid类型实例的空值.我写的测试函数正常工作:
getMempty :: (Monoid a) => a -> a
getMempty _ = mempty

> getMempty [1,2,3]
> []

我已经看过这两个问题,但我没有弄清楚答案是如何解决我的问题的:在空集中
使用Maybe在Haskell Haskell模式匹配中编写一个最大Monoid

我将如何重写maximum'函数以使其工作?

opq*_*nut 9

正如CA McCann在评论中指出的那样,你不能模仿价值,只有模式匹配.

该等式maximum' mempty = Nothing实际上等于等式maximum' x = Nothing.参数绑定到名称并Nothing返回.

这是让代码工作的一种方法:

maximum' :: (F.Foldable a, Ord b, Eq (a b), Monoid (a b)) => a b -> Maybe b
maximum' xs
  | xs == mempty = Nothing
  | otherwise    = Just $ F.foldl1 max xs
Run Code Online (Sandbox Code Playgroud)

即你可以比较xsmempty.请注意,我们需要一个Monoid约束来获取值mempty :: a b,并且Eq约束也能够进行比较.

另一个更优雅的解决方案是使用折叠区分空的和非空的情况:

maximum'' :: (F.Foldable a, Ord b) => a b -> Maybe b
maximum'' xs = F.foldl max' Nothing xs
  where max' Nothing x = Just x
        max' (Just y) x = Just $ max x y
Run Code Online (Sandbox Code Playgroud)

  • 实际上,文字是模式.请参阅haskell报告中的第3.17.1节中的语法:http://www.haskell.org/onlinereport/exps.html (5认同)
  • @MrBones:文字"模式"是通过翻译到警卫和相等检查定义的语法糖,因为您将发现是否尝试将文字与"Num"实例匹配但没有"Eq"实例.没有*固有*原因,同样的翻译也不能用于像"mempty"这样的东西,只是将这些伪模式与影响现有标识符的绑定区分开来. (5认同)

huo*_*uon 5

有几种方法可以做到这一点(@opqdonut 演示的方法很好)。还可以围绕 制作一个“最大”幺半群Maybe,并使用foldMap.

newtype Maximum a = Max { unMaximum :: Maybe a }

instance (Ord a) => Monoid (Maximum a) where
  mempty = Max Nothing
  mappend (Max Nothing) b = b
  mappend a (Max Nothing) = a
  mappend (Max (Just a)) (Max (Just b)) = Max . Just $ (max a b)

maximum' = unMaximum . F.foldMap (Max . Just)
Run Code Online (Sandbox Code Playgroud)