モナドがいっぱい!

3,760 views
3,669 views

Published on

第6回スタートHaskell発表資料
「すごいHaskell楽しく学ぼう13章」

Published in: Technology
0 Comments
14 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,760
On SlideShare
0
From Embeds
0
Number of Embeds
218
Actions
Shares
0
Downloads
51
Comments
0
Likes
14
Embeds 0
No embeds

No notes for slide
  • それでは、13章のモナドがいっぱいを発表させていただきます。\nよろしくお願いします。\n
  • まず自己紹介です。~~\nモナドってどんなイメージですか?\n
  • \n
  • \n
  • haskell.orgが計測しているモナドチュートリアルの数です。\n
  • 増えてます。\n
  • モナドを悟る => モナドチュートリアルを書くという流れがあるようですね。\n
  • \n
  • \n
  • 今日触れる型クラスはFunctor, Applicative, MonadoそしてMonadPlusです。\n
  • Functor, Applicative, Monad, MonadPlusの関係は階層構造になっていて、\nApplicativeがFunctorを継承、MonadがApplicativeを継承、そしてMonadPlusがMonadを継承しています。\n
  • \n
  • \n
  • Functorの定義はこんなでした。\n
  • Applicativeはこんな\n
  • そして真打モナドはこんな感じです。\n
  • >>=はバインドと呼ばれています。\n
  • Applicativeで出てきたpureとMonadのreturnはfとmの違いだけで同じものですね。\n
  • このへんの変な記号の関数が難所ですが、どれもなんとなく似ています。\n
  • (ピコーン)\n
  • FunctorのfmapとApplicativeのapの引数の順番を入れ替えてみましょう。\n第一引数を二番目に差し込んでいます。\n
  • そうするとこんな感じ。\nFunctorもApplicativeもMonadもすごく似てます。\n
  • \n
  • ココが違って、\n
  • \n
  • ココがおんなじです。\n
  • 順番を入れ替えた状態で改めて確認してみると、~~\n
  • \n
  • モナドは、第一引数にあるモナド値の中身の型を取って、改めて別のモナド値を返す関数が\n第二引数の位置に来ています。\n
  • \n
  • それでは具体的にMaybeモナドを見てみましょう。\n
  • Maybeモナドの定義はこんなかんじです。\n本当はfail関数などもあるのですが、あんまり重要じゃないので省略です。\n
  • \n
  • 重要なのが関数fはNothingを返すこともできるということです。\n
  • 重要なのが関数fはNothingを返すこともできるということです。\n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • モナドがいっぱい!

    1. 1. モナドがいっぱい! すごいHaskell楽しく学ぼう!13章
    2. 2. 自己紹介佐藤建太 @brain_apple東京大学 農学部 (生物系)バイトや趣味としてプログラミングしてますperl Javascript OCamlもやりたい
    3. 3. モナド、こわい?
    4. 4. モナド、難しい?
    5. 5. Monad tutorials timelinehttp://www.haskell.org/haskellwiki/Monad_tutorials_timeline
    6. 6. Monad tutorials timeline リア ル ュート ナ ドチ える モ増 http://www.haskell.org/haskellwiki/Monad_tutorials_timeline
    7. 7. やはりひとつの難関.....
    8. 8. しかし、12章までの知識でモナド理解の障壁は低くなっているはず
    9. 9. Haskellの型クラス関係図http://www.haskell.org/haskellwiki/Typeclassopedia
    10. 10. 今日触れるところHaskellの型クラス関係図http://www.haskell.org/haskellwiki/Typeclassopedia
    11. 11. Functor, Applicative, Monad, MonadPlusは、ApplicativeがFunctorを継承し、MonadがApplicativeを継承し、MonadPlusがMonadを継承しているという関係にある。
    12. 12. Monad
    13. 13. その前に、
    14. 14. Functor復習class Functor f where (<$>) :: (a -> b) -> f a -> f b
    15. 15. Applicative復習class (Functor f) => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> a -> b
    16. 16. そしてMonadclass Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
    17. 17. そしてMonadclass Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b >>= は「バインド」と呼びます
    18. 18. ApplicativeとMonadを見比べてみると、 -- Applicative pure :: a -> f a -- Monad return :: a -> m a Applicative の pure と Monad の return は同じような型で、
    19. 19. Functor, Applicative, Monadを見比べてみると、 -- Functor (<$>) :: (a -> b) -> f a -> f b -- Applicative (<*>) :: f (a -> b) -> f a -> f b -- Monad (>>=) :: m a -> (a -> m b) -> m b ムムッ、よくわからないが似たカンジがする。
    20. 20. \  __  /_ (M)_  ピコーン |ミ|/ `´  \ ( ゚∀゚) ノヽノ | < <
    21. 21. <$>と<*>の引数の型の順序を入れ替えてみると、-- Functor -- Functor(<$>) :: (a -> b) -> f a -> f b (<$>) :: f a -> (a -> b) -> f b-- Applicative -- Applicative(<*>) :: f (a -> b) -> f a -> f b (<*>) :: f a -> f (a -> b) -> f b-- Monad -- Monad(>>=) :: m a -> (a -> m b) -> m b (>>=) :: m a -> (a -> m b) -> m b
    22. 22. 第2引数の違いだけ!-- Functor(<$>) :: f a -> (a -> b) -> f b-- Applicative(<*>) :: f a -> f (a -> b) -> f b-- Monad(>>=) :: m a -> (a -> m b) -> m b
    23. 23. 第2引数の違いだけ!-- Functor(<$>) :: f a -> (a -> b) -> f b-- Applicative(<*>) :: f a -> f (a -> b) -> f b-- Monad(>>=) :: m a -> (a -> m b) -> m b
    24. 24. 第2引数の違いだけ! 違う-- Functor(<$>) :: f a -> (a -> b) -> f b-- Applicative(<*>) :: f a -> f (a -> b) -> f b-- Monad(>>=) :: m a -> (a -> m b) -> m b
    25. 25. 第2引数の違いだけ! 違う-- Functor(<$>) :: f a -> (a -> b) -> f b-- Applicative(<*>) :: f a -> f (a -> b) -> f b-- Monad(>>=) :: m a -> (a -> m b) -> m b
    26. 26. 第2引数の違いだけ! 違う-- Functor(<$>) :: f a -> (a -> b) -> f b-- Applicative(<*>) :: f a -> f (a -> b) -> f b-- Monad(>>=) :: m a -> (a -> m b) -> m b同じ 同じ
    27. 27. Functor復習-- Functor(<$>) :: f a -> (a -> b) -> f b シンプルな関数で、文脈(コンテナ) である f とは関係がない。
    28. 28. Applicative復習-- Applicative(<*>) :: f a -> f (a -> b) -> f b 文脈(コンテナ)の中の値を、 その中で写すだけ。
    29. 29. そしてMonad-- Monad(>>=) :: m a -> (a -> m b) -> m b 文脈(コンテナ)の中の値を取って、 同じ文脈だが 別の値 を返す関数
    30. 30. ふむふむ、
    31. 31. Maybeモナドで見てみよう。
    32. 32. instance Monad Maybe where -- :: x -> Maybe a return = Just -- :: Maybe a -> (a -> Maybe b) -> Maybe b Nothing >>= f = Nothing Just x >>= f = f x
    33. 33. -- return :: x -> Maybe areturn = Justreturnは受け取った値をJustでMaybeの文脈につつむだけ。
    34. 34. -- :: m a -> (a -> m b) -> m bNothing >>= f = NothingJust x >>= f = f x 第二引数の関数 f は、生の値(文脈無しの値) x を 取って、文脈付きの 別の値 を返す。 関数f は、受け取った値 x に依っては Nothingを返すこともできる!
    35. 35. -- :: m a -> (a -> m b) -> m bNothing >>= f = NothingJust x >>= f = f x 第二引数の関数 f は、生の値(文脈無しの値) x を 取って、文脈付きの 別の値 を返す。 関数f は、受け取った値 x に依っては Nothingを返すこともできる!
    36. 36. 具体例 綱渡り問題養魚場ではたらくピエールは休暇を使って綱渡りをします。(?)バランス棒を持って綱渡りします。でも、たまにバランス棒の両端に鳥が止まります。左右端の止まった鳥の数の差が4羽以上になるとバランスを崩して綱渡り失敗です。
    37. 37. 仕様鳥の数はBirds型、バランス棒はPole型landLeft n でn羽の鳥が左端に止まる。(右端も同様)落ちてない・落ちたの状態をそれぞれJustとNothingで表すモナドのバインド(>>=)で計算をつなげる
    38. 38. やりましょう
    39. 39. やりましたtype Birds = Inttype Pole = (Birds, Birds)landLeft :: Birds -> Pole -> Maybe PolelandLeft n (left, right) | abs ((left + n) - right) < 4 = Just (left + n, right) | otherwise = NothinglandRight :: Birds -> Pole -> Maybe PolelandRight n (left, right) | abs (left - (right + n)) < 4 = Just (left, right + n) | otherwise = Nothing
    40. 40. やりました 成功か失敗か 止まる鳥の数 棒の状態type Birds = Inttype Pole = (Birds, Birds)landLeft :: Birds -> Pole -> Maybe PolelandLeft n (left, right) | abs ((left + n) - right) < 4 = Just (left + n, right) | otherwise = NothinglandRight :: Birds -> Pole -> Maybe PolelandRight n (left, right) | abs (left - (right + n)) < 4 = Just (left, right + n) | otherwise = Nothing
    41. 41. こんな感じです> landLeft 2 (0, 0)Just (2, 0) -- 大丈夫(・ω<)> landLeft 6 (2, 4)Nothing -- 失敗(´;ω;`)
    42. 42. そして、
    43. 43. > :t landLeft 3landLeft 3 :: Pole -> Maybe Pole ここの型が合う> :t (>>=)(>>=) :: m a -> (a -> m b) -> m b
    44. 44. なので、
    45. 45. > :t (>>= landLeft 3)(>>= landLeft 3) :: Maybe Pole -> Maybe Pole
    46. 46. MaybeからMaybeへの関数を実現。それも、計算の失敗検出機能付き。> :t (>>= landLeft 3)(>>= landLeft 3) :: Maybe Pole -> Maybe Pole
    47. 47. 全く新しい計算が、あなたの思いのまま。
    48. 48. そう、Monad ならね。
    49. 49. > Just (0, 0) >>= landLeft 3Just (3, 0)これは成功し、> Just (0, 0) >>= landLeft 4Nothingこれは失敗です。
    50. 50. > Just (0, 0) >>= landLeft 3Just (3, 0)これは成功し、> Just (0, 0) >>= landLeft 4Nothingこれは失敗です。
    51. 51. > Just (0, 0) >>= landLeft 3Just (3, 0)これは成功し、> Just (0, 0) >>= landLeft 4Nothingこれは失敗です。
    52. 52. > Just (0, 0) >>= landLeft 1 >>= landRight 3Just (1, 3)> Just (0, 0) >>= landLeft 9 >>= landRight 9Nothing (>>=)で計算をつなげたり、 途中の失敗を最終結果として 得ることもできます
    53. 53. いつでも失敗するbananaを定義すると、途中にバナナがあればいつでも失敗しますbanana :: Pole -> Maybe Polebanana = const Nothing実行例> Just (0, 0) >>= banana >>= landLeft 1Nothing
    54. 54. ちょいまとめ
    55. 55. コンテキストの中にある値を見て成功(Just)か失敗(Nothing)かを返すことは、Functor やApplicative ではできない
    56. 56. Maybeモナドでは、コンテキストの中の値を受けてJust を返すか Nothing を返すか第2引数の関数が決めることができる(>>=) :: m a -> (a -> m b) -> m b
    57. 57. リストモナド
    58. 58. instance Monad [] where return x = [x] xs >>= f = concat (map f xs)
    59. 59. 渡されたリストの要素全てに map を通して f を適用するinstance Monad [] where return x = [x] xs >>= f = concat (map f xs)
    60. 60. 渡されたリストの要素全てに map を通して f を適用するinstance Monad [] where return x = [x] xs >>= f = concat (map f xs) そして concat でまとめ上げる
    61. 61. [3,4,5] >>= x -> [x, -x] 3 -> [3, -3] mapで 分岐して 4 -> [4, -4] 5 -> [5, -5] concatでまとめ上げる 計算結果 [3,-3,4,-4,5,-5]
    62. 62. リストモナドを使えば(>>=)でつなげると、複数の候補がある計算を自然に書ける
    63. 63. Σd(゚ ゚d)イカス!
    64. 64. MonadPlus
    65. 65. class Monad m => MonadPlus where mzero :: m a mplus :: m a -> m a -> m aMonadに適用できる関数を追加 = 機能の追加mzeroが「失敗」に当たり、mplusが「選択」に当たる。
    66. 66. 「失敗」の mzero > mzero :: Maybe () maybeでは NothingNothingになる リストでは > mzero :: [()] 空のリスト []
    67. 67. 「選択」の mplus (Maybe) > Just 1 `mplus` Just 2 左が優先 Just 1右は失敗でも > Just 1 `mplus` Nothing OK Nothing > Nothing `mplus` Just 1左がダメなら右 Just 1両方ダメなら > Nothing `mplus` Nothing 失敗 Nothing
    68. 68. 「選択」の mplus (リスト) > [1,2] `mplus` [3,4] [1,2,3,4]すべての > [1,2] `mplus` [] [1,2]選択肢を保持する。 > [] `mplus` [3,4] [3,4] > [] `mplus` [] [] ※ただリストをつなげているだけ
    69. 69. guard 失敗する値を定義するguard :: (MonadPlus m) => Bool -> m ()guard True = return ()guard False = mzero 3の倍数、もしくは3がつく数字だけを返すnabe :: Int -> [Int]nabe = x -> guard (3 `elem` show x || x `mod` 3 == 0) >> return x
    70. 70. ちゃんと動いてますね> [1..100] >>= nabe[3,6,9,12,13,15,18,21,23,24,27,30,31,32,33,34,35,36,37,38,39,42,43,45,48,51,53,54,57,60,63,66,69,72,73,75,78,81,83,84,87,90,93,96,99] ※なんで関数名が nabe なのか分からなかった人は 「世界のナベアツ」で調べてみよう!
    71. 71. ナイトの可能な動きも簡単に表せますtype Pos = (Int, Int)moveKnight :: Pos -> [Pos]moveKnight (x, y) = do (x, y) <- [(x+1,y+2),(x+2,y+1),(x-1,y-2),(x-2,y-1), (x+1,y-2),(x+2,y-1),(x-1,y+2),(x-2,y+1)] guard (x `elem` [1..8] && y `elem` [1..8]) return (x, y) 盤上にない動きを排除
    72. 72. ちなみに、guard は Control.Monad モジュールで定義されているので、使うときはここからインポートしましょう。
    73. 73. 実はAlternativeというのがあってだな...Applicative版の MonadPlusControl.Applicative モジュールで定義されているApplicative版なので MonadPlus より適用範囲は広い(はず)でも Applicative なので guard は使えないParsec などパーサーコンビネータを書くときは便利
    74. 74. Monad則もあるんだよ-- 左恒等性return a >>= k = k a-- 右恒等性m >>= return = m-- 結合性(m >>= k) >>= h = m >>= (x -> k x >>= h)
    75. 75. Monad則もあるんだよ return が id っぽく振る舞うよ-- 左恒等性return x >>= k = k x-- 右恒等性m >>= return = m-- 結合性(m >>= k) >>= h = m >>= (x -> k x >>= h)
    76. 76. Monad則もあるんだよ return が id っぽく振る舞うよ-- 左恒等性return x >>= k = k x-- 右恒等性m >>= return = m-- 結合性(m >>= k) >>= h = m >>= (x -> k x >>= h) 結合の順序は関係ないよ
    77. 77. まとめFunctor も Applicative も Monad も型が似てるMonadなら文脈(コンテナ)の中の値に直接アクセスして、  処理をコントーロールできる処理のコントロールの仕方は、その文脈に依って様々ある
    78. 78. 紹介してないモナドたちもたくさんあるので、つづく14章やいろいろなモナドを覗いてみよう!
    79. 79. ご清澄ありがとうございました。
    80. 80. 参考「すごいHaskell楽しく学ぼう!」(オーム社)Typeclassopedia (http://www.haskell.org/haskellwiki/Typeclassopedia ) ※日本語訳もあります

    ×