Haskell 中的 pure 和 mempty 有什么区别?
What is the difference between pure and mempty in Haskell?
在学校,我的任务是编写一个函数,将数字附加到列表的左侧,如果它们是偶数的话。类型签名为:
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 == []
pure 5 = [5]
那些看起来和我不太相似。特别是 mempty x
应该是 ill-typed.
基本上 mempty
给你一个 空的 东西,而 pure x
给你一个里面有 x
的东西。
您无意中使用了意想不到的幺半群,它偶然使您的代码编译通过。
当你写 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
...
你无意中将 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
,因此最终结果可能会大不相同。
在学校,我的任务是编写一个函数,将数字附加到列表的左侧,如果它们是偶数的话。类型签名为:
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 == []
pure 5 = [5]
那些看起来和我不太相似。特别是 mempty x
应该是 ill-typed.
基本上 mempty
给你一个 空的 东西,而 pure x
给你一个里面有 x
的东西。
您无意中使用了意想不到的幺半群,它偶然使您的代码编译通过。
当你写 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
...
你无意中将 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
,因此最终结果可能会大不相同。