为什么`>>`的list monad方法定义为`flip const`? [英] Why isn't the list monad method for `>>` defined as `flip const`?
问题描述
Prelude没有像这样定义列表monad有什么原因吗? (注意>>
的非标准实现。)
instance Monad []其中
m>> = k = concat(地图km)
m>> k = k - aka flip const
return x = [x]
fail s = []
我试图根据monad法律进行检查,但他们没有提及>>
。 Monad
类定义是这样的:
m>>> k = m>> = \\ __ - > k
其中 []
转换为:
concat(map(\_ - > k)m)
当然不等于 flip const
- 它们会产生明显不同的结果例如, [1..5]>>返回1
。但是,我不清楚这个默认定义是否是 law flip const
实现也会满足。
直观上,给定 的 列表monad(非确定性计算),看起来像 编辑:ehird的答案在上面出现了一个非常明显的缺陷,那就是它得到了错误的预期结果 不幸的是,我无法在明确声明的基础包的文档中找到任何地方,但我认为旧版本可能定义了 值得一提的是,您定义 可能在行为上有所不同,因为前者使用 Is there some reason why the Prelude doesn't define the list monad like this? (Note the non-standard implementation of I tried checking this against the monad laws, but they don't mention which in the which is of course not equivalent to Intuitively, given the intent of the list monad ("nondeterministic computations"), it seems like the alternative definition of EDIT: ehird's answer catches a very obvious flaw with the above, which is that it gets the wrong intended result for
Unfortunately, I can't find anywhere in the documentation for the base package where this is stated explicitly, but I think older versions may have defined For what it's worth, your definition of could differ in behaviour, since the former desugars with 这篇关于为什么`>>`的list monad方法定义为`flip const`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!>>< / code>的替代定义一样好,如果不是更好,等于只有一个。或者另一种说法是,如果我们正在处理集合而不是列表,那么这两个候选定义将是等价的。但是我在这里遗漏了一些微妙的东西,这使得
flip const
定义在列表中是错误的吗?
[]>> k
,它应该是 []
,而不是 k
。不过,我认为这个问题可以修改为这个定义:
[]>> k = []
_>> k = k
a> ;> b
必须始终等于 a>> = const b
;它只在 Monad
类中,所以你可以定义一个更高效的(但是在语义上等价的)版本。这就是为什么它不是monad法的一部分:它不是monad定义的一部分,只是typeclass(如 fail
)。
(>>)
>
Monad
typeclass。
(>>)
打破了monad用于非确定性计算的列表。由于 []
用于表示失败,因此 []>> m
必须始终为 []
;在用尽所有可能的分支之后,你无法继续!这也意味着这两个方案:
do {m; ...}
do {_< - m; ...}
>>)< / code>以及后者< code>(>> =)
。 (请参阅 Haskell 2010 Report 。)>>
.)instance Monad [] where
m >>= k = concat (map k m)
m >> k = k -- a.k.a. flip const
return x = [x]
fail s = []
>>
. The Monad
class definition is this:m >> k = m >>= \_ -> k
[]
instance would translate to this:concat (map (\_ -> k) m)
flip const
—they produce an obviously different results for, say, [1..5] >> return 1
. But it's not clear to me whether this default definition is a law that instances of Monad
must respect, or just a default implementation that satisfies some other law that the flip const
implementation would also satisfy.>>
would be just as good, if not better thanks to pruning branches that are guaranteed to be equal down to just one. Or another way of saying this is that if we were dealing with sets instead of lists, the two candidate definitions would be equivalent. But am I missing some subtlety here that makes the flip const
definition wrong for lists?[] >> k
, which should be []
, not k
. Still, I think the question can be amended to this definition:[] >> k = []
_ >> k = k
a >> b
must always be equivalent to a >>= const b
; it's only in the Monad
class so that you can define a more efficient (but semantically equivalent) version. That's why it's not part of the monad laws: it's not really part of the definition of a monad, only the typeclass (like fail
).(>>)
outside of the Monad
typeclass.(>>)
breaks the list monad's use for nondeterministic computations. Since []
is used to represent failure, [] >> m
must always be []
; you can't continue on after you've exhausted all possible branches! It would also mean that these two programs:do { m; ... }
do { _ <- m; ... }
(>>)
and the latter with (>>=)
. (See the Haskell 2010 Report.)