Haskell中的纯净和虚无有什么区别?

问题描述

在学校里,我的任务是编写一个将数字附加到列表左侧(如果它们是偶数)的函数。类型签名为:

appendIfEven :: (Applicative f,Monoid (f a),Integral a) => a -> f a -> f a

我的回答是下面的代码

appendIfEven :: (Applicative f,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,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以及我错了....

解决方法

您无意中使用了一个意外的monoid,偶然使您的代码得以编译。

当您编写mempty x `mappend` ms时,ms的值类型为f a,它是一个类半体。由于mempty x需要两个相同类型的参数,因此这会强制mappend具有相同的类型。因此,我们必须拥有

mempty x :: f a

这意味着自x :: a起,

mempty :: a -> f a

很奇怪,对吧?

好吧,碰巧库中有一个实例

instance Monoid t => Monoid (u -> t) where
   mempty = \_ -> mempty
   ...

您无意中使用了xmempty,因为在实例中t可以是f a,而u可以是a以上。 Haskell解决了monoid约束,以便使用此实例。

这也意味着

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,因此最终结果可能会非常不同。

,

考虑将其应用于列表。

mempty == []

pure 5 = [5]

那些看起来与我不太相似。特别是mempty x的输入应错误。

基本上mempty给您一个的东西,而pure x给您一个包含x的东西。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...