簡體   English   中英

為什么按這個順序列出 monad 組合?

[英]Why list monad combines in that order?

我正在閱讀關於 list monads 並遇到:

[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')]

最里面的列表是“旋轉”最快的,就像汽車的里程表一樣。

您是絕對正確的,如果括號錯誤,則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

(是的,在學習材料中省略括號是萬惡之源......不是真的,但仍然......)

隱式括號是:

 ([1,2] >>= \\n -> ['a','b']) >>= (\\ch -> return (n,ch))

這是錯誤的。 \\的優先級最低,因此會延伸到表達式的末尾。 所以括號是:

[1,2] >>= (\n -> ['a','b'] >>= (\ch -> return (n,ch)))

([1,2] >>= \\n -> ['a','b'])應該給[('a',1),('b',1),('a',2),('b',2)]

從上面的括號([1,2] >>= \\n -> ['a','b'])可以看出,實際上不是給定表達式的子表達式。 但如果是,它的結果將是['a', 'b', 'a', 'b'] n實際上並未在表達式['a', 'b']任何地方使用,因此數字不可能出現在結果中。

然后我不明白 >>= (\\ch -> return (n,ch)) 部分 - 我認為這里的 n 沒有意義。

鑒於您的括號n在那里確實是未定義的。 然而,給定適當的括號,應該清楚n來自哪里:我們仍然在\\n -> ...函數中,所以n仍然指的是該函數的參數,即[1, 2]的當前元素[1, 2]列表。

你對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']

最后一個綁定用於實際使其成為元組列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM