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'函数以使其工作?
正如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)
即你可以比较值xs对mempty.请注意,我们需要一个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)
有几种方法可以做到这一点(@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)
| 归档时间: |
|
| 查看次数: |
907 次 |
| 最近记录: |