Prelude 没有像这样定义列表单子有什么原因吗?(注意 的非标准实现>>
。)
instance Monad [] where
m >>= k = concat (map k m)
m >> k = k -- a.k.a. flip const
return x = [x]
fail s = []
我尝试根据单子定律检查这一点,但他们没有提到>>
. Monad
类定义是这样的:
m >> k = m >>= \_ -> k
在这种[]
情况下,这将转化为:
concat (map (\_ -> k) m)
这当然不等同于——它们flip const
产生明显不同的结果,例如,[1..5] >> return 1
。但是我不清楚这个默认定义是实例必须遵守的法律,还是只是满足实现也会满足Monad
的其他法律的默认实现。flip const
直观地说,鉴于 list monad 的意图>>
(“非确定性计算”),由于修剪分支保证等于一个,它的替代定义似乎同样好,如果不是更好的话。或者另一种说法是,如果我们处理的是集合而不是列表,那么两个候选定义将是等价的。但是我是否在这里遗漏了一些使flip const
列表的定义错误的微妙之处?
编辑:ehird 的回答与上述内容有一个非常明显的缺陷,即它得到了错误的预期结果[] >> k
,应该是[]
,不是k
。不过,我认为这个问题可以修改为这个定义:
[] >> k = []
_ >> k = k