为什么要按这个顺序列出 monad 组合?
Why list monad combines in that order?
我正在阅读有关列表 monad 的内容并遇到:
[1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
它产生
[(1,'a'),(1,'b'),(2,'a'),(2,'b')]
我是这样理解的:
隐式括号是:
([1,2] >>= \n -> ['a','b']) >>= (\ch -> return (n,ch))
([1,2] >>= \n -> ['a','b'])
应该给 [('a',1),('b',1),('a',2),('b',2)]
因为
instance Monad [] where
return x = [x]
xs >>= f = concat (map f xs) -- this line
fail _ = []
所以 concat (map f xs)
是 concat (map (\n -> ['a','b']) [1,2])
应该产生 [('a',1),('b',1),('a',2),('b',2)]
- 与实际输出完全相反。
然后我不明白 >>= (\ch -> return (n,ch))
部分 - 我认为这里的 n
没有意义。那个具体的推理是有缺陷的,你能解释一下这个表达式([1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
)是如何一步步计算的吗?
你的隐式括号是错误的。按照你的方式,第一个 lambda 的 n
参数不会在 return
的范围内。它更像是:
([1,2] >>= (\n -> ['a','b'] >>= (\ch -> return (n,ch))))
变成:
concatMap (\n -> concatMap (\ch -> [(n,ch)]) ['a','b']) [1,2]
不,您使用了错误的括号。它嵌套在右边,所以
[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')]
最里面的列表是 "spinning" 最快的,就像汽车的里程表一样。
您完全正确,括号错误 n
绑定将毫无意义。正是出于这个原因,它 必须 关联到右侧,才能使嵌套绑定成为可能; 嵌套计算是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
(是的,在学习中省略括号 material 是万恶之源......不是真的,但仍然......)
你对 concat (map (\n -> ['a','b']) [1,2])
语义的理解是错误的。我在下面一步一步地评估了它。
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']
最后一个绑定是用来实际使它成为元组列表的。
Implicit parentheses are:
([1,2] >>= \n -> ['a','b']) >>= (\ch -> return (n,ch))
这是错误的。 \
具有最低的优先级,因此延伸到表达式的末尾。所以括号是:
[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', 'b', 'a', 'b']
。 n
实际上并未在表达式 ['a', 'b']
中的任何位置使用,因此数字不可能出现在结果中。
Then I don't understand >>= (\ch -> return (n,ch)) part - I think that n here has no sense.
鉴于您的括号 n
确实在那里未定义。然而,如果括号正确,应该清楚 n
的来源:我们仍在 \n -> ...
函数内部,因此 n
仍然指该函数的参数,即当前元素在 [1, 2]
列表中。
我正在阅读有关列表 monad 的内容并遇到:
[1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
它产生
[(1,'a'),(1,'b'),(2,'a'),(2,'b')]
我是这样理解的:
隐式括号是:
([1,2] >>= \n -> ['a','b']) >>= (\ch -> return (n,ch))
([1,2] >>= \n -> ['a','b'])
应该给 [('a',1),('b',1),('a',2),('b',2)]
因为
instance Monad [] where
return x = [x]
xs >>= f = concat (map f xs) -- this line
fail _ = []
所以 concat (map f xs)
是 concat (map (\n -> ['a','b']) [1,2])
应该产生 [('a',1),('b',1),('a',2),('b',2)]
- 与实际输出完全相反。
然后我不明白 >>= (\ch -> return (n,ch))
部分 - 我认为这里的 n
没有意义。那个具体的推理是有缺陷的,你能解释一下这个表达式([1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
)是如何一步步计算的吗?
你的隐式括号是错误的。按照你的方式,第一个 lambda 的 n
参数不会在 return
的范围内。它更像是:
([1,2] >>= (\n -> ['a','b'] >>= (\ch -> return (n,ch))))
变成:
concatMap (\n -> concatMap (\ch -> [(n,ch)]) ['a','b']) [1,2]
不,您使用了错误的括号。它嵌套在右边,所以
[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')]
最里面的列表是 "spinning" 最快的,就像汽车的里程表一样。
您完全正确,括号错误 n
绑定将毫无意义。正是出于这个原因,它 必须 关联到右侧,才能使嵌套绑定成为可能; 嵌套计算是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
(是的,在学习中省略括号 material 是万恶之源......不是真的,但仍然......)
你对 concat (map (\n -> ['a','b']) [1,2])
语义的理解是错误的。我在下面一步一步地评估了它。
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']
最后一个绑定是用来实际使它成为元组列表的。
Implicit parentheses are:
([1,2] >>= \n -> ['a','b']) >>= (\ch -> return (n,ch))
这是错误的。 \
具有最低的优先级,因此延伸到表达式的末尾。所以括号是:
[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', 'b', 'a', 'b']
。 n
实际上并未在表达式 ['a', 'b']
中的任何位置使用,因此数字不可能出现在结果中。
Then I don't understand >>= (\ch -> return (n,ch)) part - I think that n here has no sense.
鉴于您的括号 n
确实在那里未定义。然而,如果括号正确,应该清楚 n
的来源:我们仍在 \n -> ...
函数内部,因此 n
仍然指该函数的参数,即当前元素在 [1, 2]
列表中。