我無法理解 list monad 的迭代行為是如何從它的定義中推匯出來的。
instance Monad [] where
m >>= f = concatMap f m
return x = [x]
fail s = []
我讀過的討論似乎忽略了如何>>=創建控制結構的問題,用do符號最清楚地顯示:
allEvenOdds :: Int -> [(Int,Int)]
allEvenOdds n = do
evenValue <- [2,4 .. n]
oddValue <- [1,3 .. n]
return (evenValue,oddValue)
這是內置在 Haskell 中的嗎,我假設 IO monad 與實際 i/o 的介面的方式是?
uj5u.com熱心網友回復:
沒有內置任何內容,一切都是您參考的 Monad 實體的簡單結果(并且,由于此示例使用do符號,因此該>>=運算子的使用方式如何脫糖):
allEvenOdds n = do
evenValue <- [2,4 .. n]
oddValue <- [1,3 .. n]
return (evenValue,oddValue)
-- desugaring the do notation
allEvenOdds n =
[2,4 .. n] >>= \evenValue ->
[1,3 .. n] >>= \oddValue ->
return (evenValue, oddValue)
-- using the list instance of Monad to replace >>= and return
allEvenOdds n =
concatMap (\evenValue ->
concatMap (\oddValue -> [(evenvalue, oddValue)]) [1,3 .. n])
) [2,4 .. n]
希望您可以輕松地看到“迭代”兩個串列并生成所有(偶數,奇數)對的串列,其中的值取自兩個串列。
在高層次上,我們可以說 list monad 導致迭代只是因為concatMap像 一樣map為串列的每個元素執行給定的函式,因此它隱式地迭代串列。
uj5u.com熱心網友回復:
型別類的串列實體Monad模型nondeterminism:您可以將每個實體var <- someList視為forPython 中的回圈。
該do符號被取消為[2,4 .. n] >>= (\evenValue -> [1, 3 .. n] >>= (\oddValue -> return (evenValue, oddValue))),因此這相當于 Python 中的某些內容,例如:
result = []
for evenValue in range(2, n, 2):
for oddValue in range(1, n, 2):
result.append((evenValue, oddValue))
或串列理解:
result = [
(evenValue, oddValue)
for evenValue in range(2, n, 2)
for oddValue in range(1, n, 2)
]
這適用于 for instance Monad [],因此運算式[2,4 .. n] >>= (\evenValue -> [1, 3 .. n] >>= (\oddValue -> return (evenValue, oddValue)))等效于:
concatMap (\evenValue -> [1, 3 .. n] >>= (\oddValue -> return (evenValue, oddValue))) [2,4 .. n]
因此:
concatMap (\evenValue -> concatMap (\oddValue -> [(evenValue, oddValue)]) [1, 3 .. n]) [2,4 .. n]
但是do符號不是“硬連線”到IO:IO只是一個實體,Monad它的實作方式是一個IO動作將在第二個動作之前運行。因此,對于串列,它的實作方式與跨越 Pythonfor回圈的方式相同。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/446002.html
