Haskell 哈斯凯尔的纯和记忆有什么区别?
在学校里,我的任务是写一个函数,如果数字是偶数,它会在列表的左边追加数字。类型签名为:Haskell 哈斯凯尔的纯和记忆有什么区别?,haskell,applicative,monoids,Haskell,Applicative,Monoids,在学校里,我的任务是写一个函数,如果数字是偶数,它会在列表的左边追加数字。类型签名为: 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
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:
这很有效。但是为什么呢?pure==mempty不应该吗?(在这方面)
这对我的导师来说似乎并不重要。然而,我真的想更多地了解Haskell以及我错在哪里……考虑将此应用于列表
mempty == []
pure 5 = [5]
那些看起来和我不太像。尤其是,memptyx
应该是输入错误的
基本上,
mempty
给了你一个空的东西,而pure x
给了你一个里面有x
的东西。你无意中使用了一个意外的monoid,这让你的代码得以编译
编写mempty x`mappend`ms
时,ms
值的类型为fa
,它是一个幺半群。这迫使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
可以是fa
,而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
这和
(\_ -> mempty) x `mappend` ms -- this is the mempty for (f a), instead!
mempty `mappend` ms -- this is the mempty for (f a), instead!
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
,因此最终结果可能会非常不同。例如,它们有不同的类型。如果它们有不同的类型,它们怎么可能是相同的东西呢?它之所以编译是因为a->b
有一个Monoid
实例,只要b
也是一个Monoid
,在这种情况下mempty=const mempty
@user253751a->b
有一个Monoid实例,在这种情况下,mempty
本身也是一个函数。mempty
是为monoidb=>a->b
定义为const mempty
@chepner是的,我有一种感觉,编译器不会抱怨,因为一个合适的实例确实存在,或者理论上可以使其存在。仍然不能使它成为一个合理的表达式(除非您真的在使用这样的实例)。在适当的上下文中,将mempty
用作函数是有意义的。相反,在我看来,在mempty x
中立即应用它是没有意义的,因为它与mempty
是等价的(在相同的上下文中)。函数实例使著名的技巧比较snd和比较fst
,与(fg)xy=(fxgx)y=fxyxy
成为可能。