• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
モナドがいっぱい!
 

モナドがいっぱい!

on

  • 2,713 views

第6回スタートHaskell発表資料

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

Statistics

Views

Total Views
2,713
Views on SlideShare
2,574
Embed Views
139

Actions

Likes
8
Downloads
38
Comments
0

4 Embeds 139

http://makopi23.blog.fc2.com 81
http://control.blog.fc2.com 36
https://twitter.com 21
http://cache.yahoofs.jp 1

Accessibility

Categories

Upload Details

Uploaded via as Apple Keynote

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment
  • それでは、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

モナドがいっぱい! モナドがいっぱい! Presentation Transcript

  • モナドがいっぱい! すごいHaskell楽しく学ぼう!13章
  • 自己紹介佐藤建太 @brain_apple東京大学 農学部 (生物系)バイトや趣味としてプログラミングしてますperl Javascript OCamlもやりたい
  • モナド、こわい?
  • モナド、難しい?
  • Monad tutorials timelinehttp://www.haskell.org/haskellwiki/Monad_tutorials_timeline
  • Monad tutorials timeline リア ル ュート ナ ドチ える モ増 http://www.haskell.org/haskellwiki/Monad_tutorials_timeline
  • やはりひとつの難関.....
  • しかし、12章までの知識でモナド理解の障壁は低くなっているはず
  • Haskellの型クラス関係図http://www.haskell.org/haskellwiki/Typeclassopedia
  • 今日触れるところHaskellの型クラス関係図http://www.haskell.org/haskellwiki/Typeclassopedia
  • Functor, Applicative, Monad, MonadPlusは、ApplicativeがFunctorを継承し、MonadがApplicativeを継承し、MonadPlusがMonadを継承しているという関係にある。
  • Monad
  • その前に、
  • Functor復習class Functor f where (<$>) :: (a -> b) -> f a -> f b
  • Applicative復習class (Functor f) => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> a -> b
  • そしてMonadclass Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • そしてMonadclass Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b >>= は「バインド」と呼びます
  • ApplicativeとMonadを見比べてみると、 -- Applicative pure :: a -> f a -- Monad return :: a -> m a Applicative の pure と Monad の return は同じような型で、
  • 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 ムムッ、よくわからないが似たカンジがする。
  • \  __  /_ (M)_  ピコーン |ミ|/ `´  \ ( ゚∀゚) ノヽノ | < <
  • <$>と<*>の引数の型の順序を入れ替えてみると、-- 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
  • 第2引数の違いだけ!-- Functor(<$>) :: f a -> (a -> b) -> f b-- Applicative(<*>) :: f a -> f (a -> b) -> f b-- Monad(>>=) :: m a -> (a -> m b) -> m b
  • 第2引数の違いだけ!-- Functor(<$>) :: f a -> (a -> b) -> f b-- Applicative(<*>) :: f a -> f (a -> b) -> f b-- Monad(>>=) :: m a -> (a -> m b) -> m b
  • 第2引数の違いだけ! 違う-- Functor(<$>) :: f a -> (a -> b) -> f b-- Applicative(<*>) :: f a -> f (a -> b) -> f b-- Monad(>>=) :: m a -> (a -> m b) -> m b
  • 第2引数の違いだけ! 違う-- Functor(<$>) :: f a -> (a -> b) -> f b-- Applicative(<*>) :: f a -> f (a -> b) -> f b-- Monad(>>=) :: m a -> (a -> m b) -> m b
  • 第2引数の違いだけ! 違う-- Functor(<$>) :: f a -> (a -> b) -> f b-- Applicative(<*>) :: f a -> f (a -> b) -> f b-- Monad(>>=) :: m a -> (a -> m b) -> m b同じ 同じ
  • Functor復習-- Functor(<$>) :: f a -> (a -> b) -> f b シンプルな関数で、文脈(コンテナ) である f とは関係がない。
  • Applicative復習-- Applicative(<*>) :: f a -> f (a -> b) -> f b 文脈(コンテナ)の中の値を、 その中で写すだけ。
  • そしてMonad-- Monad(>>=) :: m a -> (a -> m b) -> m b 文脈(コンテナ)の中の値を取って、 同じ文脈だが 別の値 を返す関数
  • ふむふむ、
  • Maybeモナドで見てみよう。
  • instance Monad Maybe where -- :: x -> Maybe a return = Just -- :: Maybe a -> (a -> Maybe b) -> Maybe b Nothing >>= f = Nothing Just x >>= f = f x
  • -- return :: x -> Maybe areturn = Justreturnは受け取った値をJustでMaybeの文脈につつむだけ。
  • -- :: m a -> (a -> m b) -> m bNothing >>= f = NothingJust x >>= f = f x 第二引数の関数 f は、生の値(文脈無しの値) x を 取って、文脈付きの 別の値 を返す。 関数f は、受け取った値 x に依っては Nothingを返すこともできる!
  • -- :: m a -> (a -> m b) -> m bNothing >>= f = NothingJust x >>= f = f x 第二引数の関数 f は、生の値(文脈無しの値) x を 取って、文脈付きの 別の値 を返す。 関数f は、受け取った値 x に依っては Nothingを返すこともできる!
  • 具体例 綱渡り問題養魚場ではたらくピエールは休暇を使って綱渡りをします。(?)バランス棒を持って綱渡りします。でも、たまにバランス棒の両端に鳥が止まります。左右端の止まった鳥の数の差が4羽以上になるとバランスを崩して綱渡り失敗です。
  • 仕様鳥の数はBirds型、バランス棒はPole型landLeft n でn羽の鳥が左端に止まる。(右端も同様)落ちてない・落ちたの状態をそれぞれJustとNothingで表すモナドのバインド(>>=)で計算をつなげる
  • やりましょう
  • やりました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
  • やりました 成功か失敗か 止まる鳥の数 棒の状態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
  • こんな感じです> landLeft 2 (0, 0)Just (2, 0) -- 大丈夫(・ω<)> landLeft 6 (2, 4)Nothing -- 失敗(´;ω;`)
  • そして、
  • > :t landLeft 3landLeft 3 :: Pole -> Maybe Pole ここの型が合う> :t (>>=)(>>=) :: m a -> (a -> m b) -> m b
  • なので、
  • > :t (>>= landLeft 3)(>>= landLeft 3) :: Maybe Pole -> Maybe Pole
  • MaybeからMaybeへの関数を実現。それも、計算の失敗検出機能付き。> :t (>>= landLeft 3)(>>= landLeft 3) :: Maybe Pole -> Maybe Pole
  • 全く新しい計算が、あなたの思いのまま。
  • そう、Monad ならね。
  • > Just (0, 0) >>= landLeft 3Just (3, 0)これは成功し、> Just (0, 0) >>= landLeft 4Nothingこれは失敗です。
  • > Just (0, 0) >>= landLeft 3Just (3, 0)これは成功し、> Just (0, 0) >>= landLeft 4Nothingこれは失敗です。
  • > Just (0, 0) >>= landLeft 3Just (3, 0)これは成功し、> Just (0, 0) >>= landLeft 4Nothingこれは失敗です。
  • > Just (0, 0) >>= landLeft 1 >>= landRight 3Just (1, 3)> Just (0, 0) >>= landLeft 9 >>= landRight 9Nothing (>>=)で計算をつなげたり、 途中の失敗を最終結果として 得ることもできます
  • いつでも失敗するbananaを定義すると、途中にバナナがあればいつでも失敗しますbanana :: Pole -> Maybe Polebanana = const Nothing実行例> Just (0, 0) >>= banana >>= landLeft 1Nothing
  • ちょいまとめ
  • コンテキストの中にある値を見て成功(Just)か失敗(Nothing)かを返すことは、Functor やApplicative ではできない
  • Maybeモナドでは、コンテキストの中の値を受けてJust を返すか Nothing を返すか第2引数の関数が決めることができる(>>=) :: m a -> (a -> m b) -> m b
  • リストモナド
  • instance Monad [] where return x = [x] xs >>= f = concat (map f xs)
  • 渡されたリストの要素全てに map を通して f を適用するinstance Monad [] where return x = [x] xs >>= f = concat (map f xs)
  • 渡されたリストの要素全てに map を通して f を適用するinstance Monad [] where return x = [x] xs >>= f = concat (map f xs) そして concat でまとめ上げる
  • [3,4,5] >>= x -> [x, -x] 3 -> [3, -3] mapで 分岐して 4 -> [4, -4] 5 -> [5, -5] concatでまとめ上げる 計算結果 [3,-3,4,-4,5,-5]
  • リストモナドを使えば(>>=)でつなげると、複数の候補がある計算を自然に書ける
  • Σd(゚ ゚d)イカス!
  • MonadPlus
  • class Monad m => MonadPlus where mzero :: m a mplus :: m a -> m a -> m aMonadに適用できる関数を追加 = 機能の追加mzeroが「失敗」に当たり、mplusが「選択」に当たる。
  • 「失敗」の mzero > mzero :: Maybe () maybeでは NothingNothingになる リストでは > mzero :: [()] 空のリスト []
  • 「選択」の 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
  • 「選択」の mplus (リスト) > [1,2] `mplus` [3,4] [1,2,3,4]すべての > [1,2] `mplus` [] [1,2]選択肢を保持する。 > [] `mplus` [3,4] [3,4] > [] `mplus` [] [] ※ただリストをつなげているだけ
  • 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
  • ちゃんと動いてますね> [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 なのか分からなかった人は 「世界のナベアツ」で調べてみよう!
  • ナイトの可能な動きも簡単に表せます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) 盤上にない動きを排除
  • ちなみに、guard は Control.Monad モジュールで定義されているので、使うときはここからインポートしましょう。
  • 実はAlternativeというのがあってだな...Applicative版の MonadPlusControl.Applicative モジュールで定義されているApplicative版なので MonadPlus より適用範囲は広い(はず)でも Applicative なので guard は使えないParsec などパーサーコンビネータを書くときは便利
  • Monad則もあるんだよ-- 左恒等性return a >>= k = k a-- 右恒等性m >>= return = m-- 結合性(m >>= k) >>= h = m >>= (x -> k x >>= h)
  • Monad則もあるんだよ return が id っぽく振る舞うよ-- 左恒等性return x >>= k = k x-- 右恒等性m >>= return = m-- 結合性(m >>= k) >>= h = m >>= (x -> k x >>= h)
  • Monad則もあるんだよ return が id っぽく振る舞うよ-- 左恒等性return x >>= k = k x-- 右恒等性m >>= return = m-- 結合性(m >>= k) >>= h = m >>= (x -> k x >>= h) 結合の順序は関係ないよ
  • まとめFunctor も Applicative も Monad も型が似てるMonadなら文脈(コンテナ)の中の値に直接アクセスして、  処理をコントーロールできる処理のコントロールの仕方は、その文脈に依って様々ある
  • 紹介してないモナドたちもたくさんあるので、つづく14章やいろいろなモナドを覗いてみよう!
  • ご清澄ありがとうございました。
  • 参考「すごいHaskell楽しく学ぼう!」(オーム社)Typeclassopedia (http://www.haskell.org/haskellwiki/Typeclassopedia ) ※日本語訳もあります