【发布时间】:2018-09-19 09:48:51
【问题描述】:
这个问题来自这个答案 example of a functor that is Applicative but not a Monad: 据称,
data PoE a = Empty | Pair a a deriving (Functor,Eq)
不能有 monad 实例,但我看不到:
instance Applicative PoE where
pure x = Pair x x
Pair f g <*> Pair x y = Pair (f x) (g y)
_ <*> _ = Empty
instance Monad PoE where
Empty >>= _ = Empty
Pair x y >>= f = case (f x, f y) of
(Pair x' _,Pair _ y') -> Pair x' y'
_ -> Empty
我认为这是一个 monad 的真正原因是它与 Maybe (Pair a) 和 Pair a = P a a 同构。它们都是 monad,都是可遍历的,所以它们的组合也应该形成一个 monad。 Oh, I just found out not always.
哪个反例不符合哪个单子法则? (以及如何系统地找出它?)
编辑:我没想到对这个问题有这么大的兴趣。现在我必须下定决心,是否接受“系统地”部分的最佳示例或最佳答案。
同时,我想看看join 是如何为更简单的Pair a = P a a 工作的:
P
________/ \________
/ \
P P
/ \ / \
1 2 3 4
它总是采用外部路径,产生P 1 4,通常称为矩阵表示中的对角线。对于 monad 关联我需要三个维度,树可视化效果更好。取自 chi 的回答,这是 join 的失败示例,以及我如何理解它。
Pair
_________/\_________
/ \
Pair Pair
/\ /\
/ \ / \
Pair Empty Empty Pair
/\ /\
1 2 3 4
现在您可以通过首先折叠较低级别来执行join . fmap join,因为join . join 从根折叠。
【问题讨论】:
-
我确定您已经注意到了这一点,但回复者确实回复了您对您链接的帖子的评论。我个人无法一眼就构建出符合他描述的反例,但我想让你知道他的评论。
-
使应用程序成为 Monad 的原因是能够压缩它(使用连接)并将一对转换为一对。就像您在示例中所做的那样,您不能在不丢失一些元素(从 4 到 2)的情况下做到这一点。那将触犯法律。例如
Pair (Pair 1 2) Empty >>= return返回空。这不好。 -
我在TIO 中运行它,但我没有收到
Empty -
我的意思是
>>= id -
有趣的是,非常相似的类型实际上是一个 monad:stackoverflow.com/questions/43684258/…
标签: haskell functional-programming monads