takafumi blog

日々の勉強メモ

【Haskell】 モナド簡単まとめ

環境   ghc 7.8.3 CentOS7.0

「すごいHaskellたのしく学ぼう!」第13章 メモ

簡易Monadまとめ


Monad(モナド)
▽定義
class Monad m where
    return :: a -> m a
    (>>=) :: m a -> (a -> m b) -> m b

    (>>) :: m a -> m b -> m b
    x >> y = x >>= \_ -> y

    fail :: String -> m a
    fail msg = error msg


Monadとは?

凄い簡略説明。
箱に入った値Monad m => m aに対して、a -> m bという関数を>>=を使って作用させる事。

ghci> Just "Hello" >>= \x -> Just x
Just "Hello"

作用させた値もMonadなので、>>=で連結できる。

ghci> return "Hello" >>= \x -> Just x >>= \y -> Just [y]
Just ["Hello"]


▽returnとは?

returnは値に対する最小のモナドを作成する

ghci> return 3 :: Maybe Int
Just 3

ghci> return 10 :: [Int]
[10]

ghci> :t return 1 :: IO Int
return 1 :: IO Int :: IO Int


>>は何に使う?

引数を無視して、規定の値を返すとき。
Nothing[]で使う事が多い?

ghci> Just 1 >> Just 3
Just 3

ghci> [1] >> [3]
[3]

実装は\x >>= _ -> yなので、Nothing[]のときは、常にNothing[]になる。

ghci> Nothing >> Just 1
Nothing

ghci> [] >> [1]
[]


▽failとは?

do式の中でパターンマッチが失敗した場合に、fail関数が使われる。
異常終了にはならない。

wopwop :: Maybe Char
wopwop = do
    (x:xs) <- Just "" -- パターンマッチに失敗
    return x
ghci> wopwop
Nothing

>>=中のラムダ式によるパターンマッチは異常終了する。

ghci> Just "" >>= \(x, y) -> Just (x+y)

<interactive>:1225:14:
    Couldn't match expected type ‘[Char]’ with actual type ‘(b, b)’
    Relevant bindings include
      it :: Maybe b (bound at <interactive>:1225:1)
    In the pattern: (x, y)
    In the second argument of ‘(>>=)’, namely
      ‘\ (x, y) -> Just (x + y)’
    In the expression: Just "" >>= \ (x, y) -> Just (x + y)


▽do記法で書く

>>=の式は、do記法で書き換えられる。

ghci> Just 9 >>= (\x -> Just (x >8))
Just True
foo :: Maybe Bool
foo = do
    x <- Just 9
    Just (x > 8)

ラムダ式の部分を、do記法における変数への束縛に書き換えられる。


Monad

Monadを自作する場合は、Monad則を満たす必要がある。

・左恒等性

return を使って値をデフォルトの文脈に入れたものを >>= を使って関数に食わせた結果は、単にその値にその関数を適用した結果と等しくなりなさい、ということです。形式的に言えば、return x >>= f と f x は等価である

ghci> return 3 >>= (\x -> Just (x+10000))
Just 10003

ghci> (\x -> Just (x+10000)) 3
Just 10003

・右恒等性

= を使ってモナド値を return に食わせた結果は、元のモナド値と不変であると言っています。式で書くと、 m >>= return はただの m である

ghci> Just "hello" >>= return
Just "hello"
ghci> [1..3] >>= return
[1,2,3]

結合法則

= を使ったモナド関数適用の連鎖があるときに、どの順序で評価しても結果は同じであるべき、というものです。式で書くと、(m >>= f) >>= g と m >>= (\x -> f x >>= g) が等価である

ghci> Just 1 >>= \x -> Just (x + 2) >>= \y -> Just (y * 3)
Just 9
ghci> Just 1 >>= (\x -> Just (x + 2) >>= \y -> Just (y * 3))
Just 9
ghci> (Just 1 >>= \x -> Just (x + 2)) >>= \y -> Just (y * 3)
Just 9

takafumi-s.hatenablog.com