haskell - Haskell 中的 pure 和 mempty 有什么区别?
问题描述
在学校,我的任务是编写一个函数,将数字附加到列表的左侧,如果它们是偶数的话。类型签名如下:
appendIfEven :: (Applicative f, Monoid (f a), Integral a) => a -> f a -> f a
我的答案是以下代码
appendIfEven :: (Applicative f, Monoid (f a), Integral a) => a -> f a -> f a
appendIfEven x ms = if x `mod` 2 == 0 then mempty x `mappend` ms else ms
Haskell 可以编译我的代码,但不能正常工作。经过一些实验,我将mempty切换为pure:
appendIfEven :: (Applicative f, Monoid (f a), Integral a) => a -> f a -> f a
appendIfEven x ms = if x `mod` 2 == 0 then pure x `mappend` ms else ms
哪个工作得很好。但为什么 ?不应该pure == mempty吗?(在这种情况下)这对我的导师来说似乎并不重要。但是我真的很想了解更多关于 Haskell 以及我错在哪里......
解决方案
你无意中使用了一个意想不到的幺半群,它顺便让你的代码编译了。
当您编写mempty x `mappend` ms
时,该ms
值具有 type f a
,这是一个幺半群。这强制mempty x
具有相同的类型,因为mappend
需要两个相同类型的参数。因此我们必须有
mempty x :: f a
这意味着,因为x :: a
,
mempty :: a -> f a
很奇怪,对吧?
好吧,库中恰好有一个实例
instance Monoid t => Monoid (u -> t) where
mempty = \_ -> mempty
...
您无意中使用了传递x
给mempty
, 因为t
可以是f a
, 并且u
可以a
在上面的实例中。Haskell 解决了幺半群约束以便使用这个实例。
这也意味着
mempty x `mappend` ms
是相同的
(\_ -> mempty) x `mappend` ms -- this is the mempty for (f a), instead!
这与
mempty `mappend` ms -- this is the mempty for (f a), instead!
这与
ms
因此,您的代码完全忽略了该x
参数。
相比之下,在一般情况下pure x
确实取决于x
,因此最终结果可能会非常不同。
推荐阅读
- aws-lambda - 获取供应商层的 ARN
- c# - tcp/ip c# 服务器连接被拒绝
- python - 如何在带有交替的正则表达式中获取匹配的单词?
- reactjs - 具有两个参数的反应路线不适用于反应构建
- javascript - 是否可以使用 Node.js 和 Express 传递带有 request.query 的对象数组?
- reactjs - 使用 React Context API 传递 React 函数时重新渲染的问题
- mysql - 如何排序这个 MySQL 查询
- c# - 关闭一个表单并显示另一个
- javascript - 如何使用 jQuery 创建淡入淡出循环
- microsoft-cognitive - 如何使用 JavaScript 将一批图像上传到 Azure 自定义视觉