1

を使用しghciて計算しました:

Prelude> let m = [1,2]
Prelude> let ys = [4, 5, 6]
Prelude> m >>= (\x -> ys >>= (\y -> return (x, y)))
[(1,4),(1,5),(1,6),(2,4),(2,5),(2,6)]

上記のモナド式は、モナド結合法則のどちらの側にも対応していないようです。

(m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)

モナド結合性を式に適用する方法を知りたい:

m >>= (\x -> ys >>= (\y -> return (x, y))) 

は周囲の関数とそれを含む関数の両方で閉じているためreturn (x,y)、結合法則の左側に存在する中間モナド(m >>= f)はこの例では存在できないようです。

4

3 に答える 3

3

実際、x元の式の の範囲により、結合法則を直接適用することはできません。

import Control.Monad (liftM)

test = let m = [1,2]
           ys = [4, 5, 6]
       in m >>= (\x -> ys >>= (\y -> return (x, y)))

xただし、最初のモナド計算の結果に含めると、 のスコープを縮小できます。を返す代わりに[Int]x -> ysと を使用します。ここで、各ペアの最初の数値は常にであり、2 番目の数値は のいずれかです。( for リストは と同じであることに注意してください。) そして、2 番目の関数は、その入力からの値を読み取ります。\x -> liftM ((,) x) ys[(Int,Int)]xysliftMmapx

test1 = let m = [1,2]
            ys = [4, 5, 6]
        in m >>= (\x -> liftM ((,) x) ys >>= (\(x', y) -> return (x', y)))

(モナド関数\(x', y) -> return (x', y)は に単純化されreturn、その後>>= return完全に削除される可能性がありますが、引数のためにそのままにしておきます。)

これで、各モナド関数は自己完結型になり、結合法則を適用できます。

test2 = let m = [1,2]
            ys = [4, 5, 6]
        in (m >>= \x -> liftM ((,) x) ys) >>= (\(x, y) -> return (x, y))
于 2014-03-02T07:06:24.270 に答える
1

単項法則は、引数が 1 つの関数のみに適用されます。表現

xs >>= (\x -> ys >>= (\y -> (x, y)))

実際には次と同等です:

xs >>= \x -> fmap ($ x) $ ys >>= \y -> return (\x -> (x,y))

(キャプチャを避ける場合x

したがって、同じ法則を適用することはできません。結合法則からfmapasfと noがあります。g

上記はもちろん次と同じです。

xs >>= \x -> fmap ($ x) $ fmap (\y x -> (x,y)) ys

また

xs >>= \x -> fmap (\y -> (x,y)) ys
于 2014-03-04T10:09:07.667 に答える