mapM return [1..]
これは、終了しない証明の試みです。しばらくの間、モナドにいると仮定しましょうIdentity
(この引数は他のモナドにも同様に適用されます):
mapM return [1..] -- initial expression
sequence (map return [1 ..]) -- unfold mapM
let k m m' = m >>= \x ->
m' >>= \xs ->
return (x : xs)
in foldr k (return []) (map return [1..]) -- unfold sequence
ここまでは順調ですね...
-- unfold foldr
let k m m' = m >>= \x ->
m' >>= \xs ->
return (x : xs)
go [] = return []
go (y:ys) = k y (go ys)
in go (map return [1..])
-- unfold map so we have enough of a list to pattern-match go:
go (return 1 : map return [2..])
-- unfold go:
k (return 1) (go (map return [2..])
-- unfold k:
(return 1) >>= \x -> go (map return [2..]) >>= \xs -> return (x:xs)
return a = Identity a
Identity モナドと Identity モナドでそれを思い出してください(Identity a) >>= f = f a
。続き:
-- unfold >>= :
(\x -> go (map return [2..]) >>= \xs -> return (x:xs)) 1
-- apply 1 to \x -> ... :
go (map return [2..]) >>= \xs -> return (1:xs)
-- unfold >>= :
(\xs -> return (1:xs)) (go (map return [2..]))
この時点で に申し込みたいと思っていますが\xs
、まだできません。代わりに、適用する値が得られるまで展開を続ける必要があります。
-- unfold map for go:
(\xs -> return (1:xs)) (go (return 2 : map return [3..]))
-- unfold go:
(\xs -> return (1:xs)) (k (return 2) (go (map return [3..])))
-- unfold k:
(\xs -> return (1:xs)) ((return 2) >>= \x2 ->
(go (map return [3..])) >>= \xs2 ->
return (x2:xs2))
-- unfold >>= :
(\xs -> return (1:xs)) ((\x2 -> (go (map return [3...])) >>= \xs2 ->
return (x2:xs2)) 2)
この時点では、まだ に申請できませんが\xs
、 に申請することはできます\x2
。続き:
-- apply 2 to \x2 :
(\xs -> return (1:xs)) ((go (map return [3...])) >>= \xs2 ->
return (2:xs2))
-- unfold >>= :
(\xs -> return (1:xs)) (\xs2 -> return (2:xs2)) (go (map return [3..]))
\xs
これで、どちらも \xs2
減らすこともできないところまで来ました。私たちの唯一の選択肢は次のとおりです。
-- unfold map for go, and so on...
(\xs -> return (1:xs))
(\xs2 -> return (2:xs2))
(go ((return 3) : (map return [4..])))
ご覧のとおり、 のおかげでfoldr
、適用する一連の関数を作成しています。リストの最後から始めて、上に向かって作業を進めています。各ステップで入力リストが無限であるため、この展開が終了することはなく、答えが得られることもありません。
これは、この例を見ると理にかなっています (別の StackOverflow スレッドから借用したもので、現時点ではどれを見つけることができません)。以下のモナドのリスト:
mebs = [Just 3, Just 4, Nothing]
sequence
をキャッチしNothing
て、全体の失敗を返すことが期待されます。
sequence mebs = Nothing
ただし、このリストの場合:
mebs2 = [Just 3, Just 4]
シーケンスが私たちに与えることを期待します:
sequence mebs = Just [3, 4]
言い換えれば、正しい答えを見つけるために、モナド計算のリスト全体を見sequence
て、それらをつなぎ合わせ、それらすべてを実行する必要があります。sequence
リスト全体を見ないで答えを出す方法はありません。
注:この回答の以前のバージョンでfoldr
は、リストの後ろから計算し、無限リストではまったく機能しないと主張していましたが、それは正しくありません! 渡す演算子のfoldr
2 番目の引数が遅延していて、リストのような遅延データ コンストラクターを使用して出力を生成する場合、foldr
は無限リストで問題なく機能します。例については、を参照foldr (\x xs -> (replicate x x) ++ xs) [] [1...]
してください。しかし、私たちの operator はそうではありませんk
。