[英]Why list monad combines in that order?
I was reading about list monads and encountered:我正在阅读关于 list monads 并遇到:
[1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
it produces它产生
[(1,'a'),(1,'b'),(2,'a'),(2,'b')]
Here's how I understand it:以下是我的理解:
Implicit parentheses are:隐式括号是:
([1,2] >>= \n -> ['a','b']) >>= (\ch -> return (n,ch))
([1,2] >>= \\n -> ['a','b'])
should give [('a',1),('b',1),('a',2),('b',2)]
([1,2] >>= \\n -> ['a','b'])
应该给[('a',1),('b',1),('a',2),('b',2)]
because因为
instance Monad [] where
return x = [x]
xs >>= f = concat (map f xs) -- this line
fail _ = []
so concat (map f xs)
is concat (map (\\n -> ['a','b']) [1,2])
which should produce [('a',1),('b',1),('a',2),('b',2)]
- quite the opposite of the actual output.所以
concat (map f xs)
是concat (map (\\n -> ['a','b']) [1,2])
应该产生[('a',1),('b',1),('a',2),('b',2)]
- 与实际输出完全相反。
Then I don't understand >>= (\\ch -> return (n,ch))
part - I think that n
here has no sense.然后我不明白
>>= (\\ch -> return (n,ch))
部分 - 我认为这里的n
没有意义。 That specific reasoning is flawed, could you please explain how that expression( [1,2] >>= \\n -> ['a','b'] >>= \\ch -> return (n,ch)
) is computed step-by-step?那个具体的推理是有缺陷的,你能解释一下表达式(
[1,2] >>= \\n -> ['a','b'] >>= \\ch -> return (n,ch)
) 是如何一步一步计算?
Your implicit parentheses are wrong.你的隐式括号是错误的。 The way you have it, the
n
parameter to the first lambda would not be in scope in the return
.按照您的方式,第一个 lambda 的
n
参数不会在return
范围内。 It is more like:它更像是:
([1,2] >>= (\n -> ['a','b'] >>= (\ch -> return (n,ch))))
Which becomes:变成:
concatMap (\n -> concatMap (\ch -> [(n,ch)]) ['a','b']) [1,2]
No, you're using wrong parenthesization.不,您使用了错误的括号。 It's nested to the right, so that
它嵌套在右侧,因此
[1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
=
[1,2] >>= (\n -> ['a','b'] >>= (\ch -> return (n,ch) ))
=
do { n <- [1,2]
; do { ch <- ['a','b']
; return (n,ch) }}
=
for n in [1,2]: -- pseudocode
for ch in ['a','b']:
return (n,ch)
=
[ r | n <- [1,2], ch <- ['a','b'], r <- [(n,ch)] ] -- return == (:[])
=
[ (n,ch) | n <- [1,2], ch <- ['a','b'] ]
=
pure (,) <*> [1,2] <*> ['a','b'] -- using list applicative
=
[(1,'a'), (1,'b'), (2,'a'), (2,'b')]
and the innermost list is "spinning" the fastest, like in a car's odometer.最里面的列表是“旋转”最快的,就像汽车的里程表一样。
You are absolutely right, with the wrong parenthesization the n
binding would make no sense.您是绝对正确的,如果括号错误,则
n
绑定将毫无意义。 It is precisely for that reason that it must associate to the right, to make the nested binding possible;正是因为这个原因,它必须关联到右边,才能使嵌套绑定成为可能; for the nested computations are the essence of the monad:
因为嵌套计算是 monad 的本质:
[ foo x | x <- xs ] -- functor : amendable computations
[ bar x y | x <- xs AND y <- ys ] -- applicative : combinable computations
[ baz x y | x <- xs, y <- foo x ] -- monad : reinterpretative computations
(and yes, omitting parentheses in learning material is the root of all evil... not really, but still...) (是的,在学习材料中省略括号是万恶之源......不是真的,但仍然......)
Implicit parentheses are:
隐式括号是:
([1,2] >>= \\n -> ['a','b']) >>= (\\ch -> return (n,ch))
This is wrong.这是错误的。
\\
has the lowest precedence and thus extends to the end of the expression. \\
的优先级最低,因此会延伸到表达式的末尾。 So the parentheses are:所以括号是:
[1,2] >>= (\n -> ['a','b'] >>= (\ch -> return (n,ch)))
([1,2] >>= \\n -> ['a','b'])
should give[('a',1),('b',1),('a',2),('b',2)]
([1,2] >>= \\n -> ['a','b'])
应该给[('a',1),('b',1),('a',2),('b',2)]
As you can see from the above parenthesization ([1,2] >>= \\n -> ['a','b'])
, isn't actually a subexpression of the given expression.从上面的括号
([1,2] >>= \\n -> ['a','b'])
可以看出,实际上不是给定表达式的子表达式。 But if it were, its result would be ['a', 'b', 'a', 'b']
.但如果是,它的结果将是
['a', 'b', 'a', 'b']
。 n
is not actually used anywhere in the expressions ['a', 'b']
, so there's no way the numbers could appear in the result. n
实际上并未在表达式['a', 'b']
任何地方使用,因此数字不可能出现在结果中。
Then I don't understand >>= (\\ch -> return (n,ch)) part - I think that n here has no sense.
然后我不明白 >>= (\\ch -> return (n,ch)) 部分 - 我认为这里的 n 没有意义。
Given your parenthesization n
would indeed be undefined there.鉴于您的括号
n
在那里确实是未定义的。 However given the proper parenthesization it should be clear where n
comes from: We're still inside the \\n -> ...
function, so n
still refers to the argument of that function, namely the current element of the [1, 2]
list.然而,给定适当的括号,应该清楚
n
来自哪里:我们仍然在\\n -> ...
函数中,所以n
仍然指的是该函数的参数,即[1, 2]
的当前元素[1, 2]
列表。
You're wrong about the semantics of concat (map (\\n -> ['a','b']) [1,2])
.你对
concat (map (\\n -> ['a','b']) [1,2])
的语义是错误的。 I've done a step by step evaluation of it below.我在下面对其进行了逐步评估。
concat (map (\\n -> ['a','b']) [1,2])
concat [(\\n -> ['a','b']) 1, (\\n -> ['a','b']) 2]
concat [['a','b'], ['a','b']]
['a','b','a','b']
The last bind is what is used to actually make it a list of tuples.最后一个绑定用于实际使其成为元组列表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.