ファンクターからアプリカティブファンクターへ     @UsrNameu1
自己紹介@UsrNameu1・新卒社会人一年目・大学では物理を専攻・院に行くはずだったけどちょっと悩んで社会人・職場近いんで神保町でひょっこり会うかも知れません・Haskellを始めた理由は数学に近そうな言語だったから・趣味は登山と囲碁です
ファンクター復習(7章より)ファンクターとは?・全体を写せる(map over)性質をもつ型クラス型クラス実装class Functor f wherefmap :: (a -> b) -> f a -> f bf:型コンストラクタ(:k f ...
CASE1:LISTFunctor インスタンス宣言instance Functor [] where    fmap = mapmap :: (a->b) -> [a] -> [b]↑(:k [] で []:*->*が返ってくる)ghci> ...
CASE2:MAYBEFunctor インスタンス宣言instance Functor Maybe where    fmap f (Just x) = Just (f x)    fmap f Nothing = Nothing↑(:k Ma...
CASE3:IO(ここから11章)Functor インスタンス宣言instance Functor IO where    fmap f action = do        result <- action        return (f ...
CASE3:IO(ここから11章)main = do line <- getLine          let line’ = reverse line          putStrLn $ “You said “ ++ line’ ++ “...
CASE3:IO(ここから11章)p195 todo.hs sourceview :: [String] -> IO ()view [fileName] = do     contents <- readFile fileName     le...
CASE4:((->) r)そもそも(->)とは?⇢函数引数と返り値の型を(ー>)で区切り、返り値の型を常に宣言の最後に置く(p25)                  ↓              視点を変えて(ー>)を2つの型をとって函数を...
CASE4:((->) r)ー>のままではFunctorとして使えないため一つ引数の型rをとって((->) r)を新しいFunctorと見立てる(∵ :k ((->) Int) ▶ ((->) Int) :: * -> *)          ...
「文脈」のお話Functor クラス実装class Functor f where    fmap :: (a -> b) -> f a -> f bのfを文脈(Computational context)と呼ぶ例:(->) r  型入力を一つ...
「持ち上げ」のお話(ー>)を2つの型をとって函数を返す型コンストラクタと見立てるclass Functor f where    fmap :: (a -> b) -> f a -> f b                       ↓ クラ...
「持ち上げ」のお話例:ghci> let shout = fmap (++ “!”)ghci> :t shoutshout :: Functor f => f [Char] -> f [Char]ghci> shout [“ha”,“ka”,“...
ファンクター則Functorクラスのインスタンスには2つのきまりがある第一法則(恒等函数の保存)fmap id (f a) = id (f a)第二法則(合成函数の分配)fmap (g . h) (f a) = fmap g (fmap h (...
ファンクター則例:(->) rinstance Functor ((->) r) where    fmap f g = f . g第一則: fmap id g = id . g = id (g)第二則: fmap (f . g) h = f ...
ファンクター則を満たさないファンクターdata CMaybe a = CNothing              | CJust Int a deriving (Show)instance Functor CMaybe where    fma...
アプリカティブファンクター二引数函数をfmapを用いてFunctor値に適用してみる例:ghci>:t   fmap (++) (Just “hey”)  fmap   (++) (Just “hey”) :: Maybe([Char] -> ...
アプリカティブファンクターこのFunctor内部の函数を使ってFunctor値を写したい! しかし、普通に適用しようとすると…例:ghci> let a = fmap (++) (Just “hey”)ghci> fmap a (Just “ ...
アプリカティブファンクターControl.Applicativeモジュール内class (Functor f) => Applicative f where    pure :: a -> f a    (<*>) :: f (a -> b) ...
アプリカティブファンクター例1:Maybe Applicative Functorinstance Applicative Maybe where    pure = Just    Nothing <*> _ = Nothing    (Ju...
アプリカティブファンクター便利な記号<$>pure (+) <*> Just 3 <*> Just 5をもっと簡潔にしたい!アプリカティブ則(ファンクタ則のようなもの)の一つにpure f <*> x = fmap f x があり更に短くf <...
アプリカティブファンクター例2:List Applicative Functorinstance Applicative [] where    pure x = [x]    fs <*> xs = [f x| f <- fs, x <- x...
アプリカティブファンクター例3:IO Applicative Functorinstance Applicative IO where    pure = return    a <*> b = do        f <- a        ...
アプリカティブファンクター例4:((->) r) Applicative Functorinstance Applicative ((->) r) where    pure x = (_ -> x)    f <*> g = x -> f x...
アプリカティブファンクター例5:ZipList Applicative Functorinstance Applicative ZipList where    pure x = ZipList (repeat x)    ZipList fs...
アプリカティブ則アプリカティブファンクターにもファンクター則同様に写像性    pure f <*> x = fmap f x恒等函数保存 pure id <*> v = v分配則    pure (.) <*> u <*> v <*> w  ...
アプリカティブの便利な函数達Control.Applicative内には<$>の他にもliftA2::(Applicative f) => (a->b->c)                        -> f a -> f b -> f ...
アプリカティブの便利な函数達他にも自分で便利な函数を作れるsequenceA :: (Applicative f) => [f a] -> f [a]sequenceA [] = pure []sequenceA (x:xs) = (:) <$...
Applicative functor
Upcoming SlideShare
Loading in …5
×

Applicative functor

3,266 views

Published on

StartHaskell2(12/10/13) 資料

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

No Downloads
Views
Total views
3,266
On SlideShare
0
From Embeds
0
Number of Embeds
256
Actions
Shares
0
Downloads
18
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide
  • \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
  • Applicative functor

    1. 1. ファンクターからアプリカティブファンクターへ @UsrNameu1
    2. 2. 自己紹介@UsrNameu1・新卒社会人一年目・大学では物理を専攻・院に行くはずだったけどちょっと悩んで社会人・職場近いんで神保町でひょっこり会うかも知れません・Haskellを始めた理由は数学に近そうな言語だったから・趣味は登山と囲碁です
    3. 3. ファンクター復習(7章より)ファンクターとは?・全体を写せる(map over)性質をもつ型クラス型クラス実装class Functor f wherefmap :: (a -> b) -> f a -> f bf:型コンストラクタ(:k f で f:: *->* を返す)
    4. 4. CASE1:LISTFunctor インスタンス宣言instance Functor [] where fmap = mapmap :: (a->b) -> [a] -> [b]↑(:k [] で []:*->*が返ってくる)ghci> fmap (*2) [1..3][2,4,6]
    5. 5. CASE2:MAYBEFunctor インスタンス宣言instance Functor Maybe where fmap f (Just x) = Just (f x) fmap f Nothing = Nothing↑(:k MaybeでMaybe::*->*が返ってくる)ghci>fmap (*2) (Just 200)Just 400 _人人人人人人人人人人人_  >箱の中身だけを変えて返す<  ̄^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄
    6. 6. CASE3:IO(ここから11章)Functor インスタンス宣言instance Functor IO where fmap f action = do result <- action return (f result)↑resultに束縛されたactionにfを適用して返す⇢何が嬉しいのか?
    7. 7. CASE3:IO(ここから11章)main = do line <- getLine let line’ = reverse line putStrLn $ “You said “ ++ line’ ++ “ backwards!” putStrLn $ “Yes, you said “ ++ line’ ++ “ backwards!” ↓main = do line <- fmap reverse getLine putStrLn $ “You said “ ++ line ++ “ backwards!” putStrLn $ “Yes, you said “ ++ line ++ “ backwards!” ↓ …ちょっと、嬉しい
    8. 8. CASE3:IO(ここから11章)p195 todo.hs sourceview :: [String] -> IO ()view [fileName] = do contents <- readFile fileName let todoTasks = lines contents numberedTasks = zipWith (n line -> show n ++ " - " ++ line) [0..] todoTasks putStr $ unlines numberedTasks ↓view :: [String] -> IO ()view [fileName] = do numberedTasks <- fmap (zipWith (n line -> show n ++ " - " ++ line) [0..] . lines ) $readFile fileName putStr $ unlines numberedTasks ↓ なかなか嬉しい!
    9. 9. CASE4:((->) r)そもそも(->)とは?⇢函数引数と返り値の型を(ー>)で区切り、返り値の型を常に宣言の最後に置く(p25) ↓ 視点を変えて(ー>)を2つの型をとって函数を返す型コンストラクタと見立てる (実際 :k (->) で(->) :: * -> * -> * を返す)
    10. 10. CASE4:((->) r)ー>のままではFunctorとして使えないため一つ引数の型rをとって((->) r)を新しいFunctorと見立てる(∵ :k ((->) Int) ▶ ((->) Int) :: * -> *) ↓Functor インスタンス宣言instance Functor ((->) r) where fmap f g = (x -> f (g x)) fmap = (.) fmap::(a->b)->((->)r a)->((->)r b)= fmap::(a->b)->(r->a)->(r->b)
    11. 11. 「文脈」のお話Functor クラス実装class Functor f where fmap :: (a -> b) -> f a -> f bのfを文脈(Computational context)と呼ぶ例:(->) r  型入力を一つすると函数型を返す文脈[]    型入力を一つするとリスト型を返す文脈
    12. 12. 「持ち上げ」のお話(ー>)を2つの型をとって函数を返す型コンストラクタと見立てるclass Functor f where fmap :: (a -> b) -> f a -> f b  ↓ クラス実装の視点を変えて fmap :: (a -> b) -> (f a -> f b)と見て、fmapを「元の函数と似てるけどFunctor値をとってFunctor値を返す函数」を返すメソッドと見立てることもできる。この操作を持ち上げ(lifting)と呼ぶ。
    13. 13. 「持ち上げ」のお話例:ghci> let shout = fmap (++ “!”)ghci> :t shoutshout :: Functor f => f [Char] -> f [Char]ghci> shout [“ha”,“ka”,“ta”,”no”][“ha!”,“ka!”,”ta!”,”no!”] 「持ち上げられた函数」※これまでの fmapが函数とFunctor値を引数とする二引数函数である 見方が否定されたわけではない。
    14. 14. ファンクター則Functorクラスのインスタンスには2つのきまりがある第一法則(恒等函数の保存)fmap id (f a) = id (f a)第二法則(合成函数の分配)fmap (g . h) (f a) = fmap g (fmap h (f a))※法則は数学的要請(圏論)による、下記リンクを参照http://ja.wikibooks.org/wiki/Haskell/%E5%9C%8F%E8%AB%96
    15. 15. ファンクター則例:(->) rinstance Functor ((->) r) where fmap f g = f . g第一則: fmap id g = id . g = id (g)第二則: fmap (f . g) h = f . g . h     = f (g . h)     = fmap f (g . h)     = fmap f (fmap g h)
    16. 16. ファンクター則を満たさないファンクターdata CMaybe a = CNothing | CJust Int a deriving (Show)instance Functor CMaybe where fmap f CNothing = CNothing fmap f (CJust count x) = CJust (count+1) (f x) fmap id (CJust 0 “haha”)≠ id (CJust 0 “haha”) より第一則: fmap id (f a) = id (f a) を満たさず、Functorとして不適切
    17. 17. アプリカティブファンクター二引数函数をfmapを用いてFunctor値に適用してみる例:ghci>:t fmap (++) (Just “hey”)  fmap (++) (Just “hey”) :: Maybe([Char] -> [Char])Functor内部に函数が入った! ↑カリー化された複数引数函数に部分適用が施され、函数を値として返すため (p62参照)
    18. 18. アプリカティブファンクターこのFunctor内部の函数を使ってFunctor値を写したい! しかし、普通に適用しようとすると…例:ghci> let a = fmap (++) (Just “hey”)ghci> fmap a (Just “ you!”)<interactive>:31:6: Couldnt match expected type `a0 -> b0 with actual type `Maybe ([Char] -> [Char]) In the first argument of `fmap, namely `a In the expression: fmap a (Just " you!") In an equation for `it: it = fmap a (Just " you!") _人人人人人人人_となり、うまくいかない >アプリカティブ <             そこで! > ファンクター <  ̄^Y^Y^Y^Y^Y^Y^Y
    19. 19. アプリカティブファンクターControl.Applicativeモジュール内class (Functor f) => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f bpureは文脈内に型を置く函数(<*>)はfmapの函数引数が文脈内にあっても適用可能なグレードアップバージョン
    20. 20. アプリカティブファンクター例1:Maybe Applicative Functorinstance Applicative Maybe where pure = Just Nothing <*> _ = Nothing (Just f) <*> sth = fmap f sthghci> let a = fmap (++) (Just “hey”)ghci> a <*> (Just “ you!”)Just "hey you!"※普通のファンクターの場合ファンクター内の関数適用の結果をファンクター外に 取り出す一般的な方法は無い。
    21. 21. アプリカティブファンクター便利な記号<$>pure (+) <*> Just 3 <*> Just 5をもっと簡潔にしたい!アプリカティブ則(ファンクタ則のようなもの)の一つにpure f <*> x = fmap f x があり更に短くf <$> xと書ける(Control.Applicative内)(<$>) :: (Functor f) => (a->b) -> f a -> f bf <$> x = fmap f x (ちなみにghci> :t ($) ▶ ($) :: (a -> b) -> a -> b )
    22. 22. アプリカティブファンクター例2:List Applicative Functorinstance Applicative [] where pure x = [x] fs <*> xs = [f x| f <- fs, x <- xs]ghci> pure “Hey” :: [String][“Hey”] (::=型注釈,p30参照)・定義から可能な組み合わせ全てをリストとして提示するghci> filter (>50) $ (*) <$> [2,5,10] <*> [8,10,11][55,80,100,110] (::=型注釈,p30参照)
    23. 23. アプリカティブファンクター例3:IO Applicative Functorinstance Applicative IO where pure = return a <*> b = do f <- a x <- b return (f x)ghci> (++) <$> getLine <*> getLinehgoaihgolk"hgoaihgolk"
    24. 24. アプリカティブファンクター例4:((->) r) Applicative Functorinstance Applicative ((->) r) where pure x = (_ -> x) f <*> g = x -> f x (g x) pure :: a -> (r -> a)(<*>) :: (r -> (a -> b)) -> (r -> a) -> (r -> b)ghci> (+) <$> (+3) <*> (*100) $ 5508(ここで:t (+) <$> (+3) ▶ (+) <$> (+3) :: Num a => a -> a -> a)ghci> (x y z -> [x,y,z]) <$> (+3) <*> (*2) <*> (/2) $ 5[8.0,10.0,2.5]・<*>,<$>は頭の函数に引数函数を渡す為の道具と割切る
    25. 25. アプリカティブファンクター例5:ZipList Applicative Functorinstance Applicative ZipList where pure x = ZipList (repeat x) ZipList fs <*> ZipList xs = ZipList (zipWith (f x -> f x) fs xs)・[]の<*>は可能な組み合わせすべてを結果に出す・ZipListの<*>はリストの個々の函数を対応する位置の 値に適用して結果に出す・ZipListをアプリカティブ・スタイルで使えばzipWith 函数群を使う必要がない
    26. 26. アプリカティブ則アプリカティブファンクターにもファンクター則同様に写像性    pure f <*> x = fmap f x恒等函数保存 pure id <*> v = v分配則    pure (.) <*> u <*> v <*> w       = u <*> (v <*> w)準同型    pure f <*> pure x = pure (f x)交換則    u <*> pure y = pure ($ y) <*> uが成立
    27. 27. アプリカティブの便利な函数達Control.Applicative内には<$>の他にもliftA2::(Applicative f) => (a->b->c) -> f a -> f b -> f cliftA2 f a b = f <$> a <*> bやその他様々有用な函数(<$,<**>,liftA3..)が存在また、ユーザ定義により(<*),(*>),等の函数も使えるようになるらしい。詳しくは以下URLを参照http://www.haskell.org/ghc/docs/6.12.1/html/libraries/base/Control-Applicative.html
    28. 28. アプリカティブの便利な函数達他にも自分で便利な函数を作れるsequenceA :: (Applicative f) => [f a] -> f [a]sequenceA [] = pure []sequenceA (x:xs) = (:) <$> x <*> sequenceA xsghci> sequenceA [Just 1,Just 2]Just [1,2]ghci> sequenceA [(>4),(<10),odd] 7[True,True,True]ghci> sequenceA [[1,2],[3,4],[5,6]][[1,3,5],[1,3,6],[1,4,5],[1,4,6],[2,3,5],[2,3,6],[2,4,5],[2,4,6]]ghci> sequenceA [getLine,getLine]hogehogemogemoge["hogehoge","mogemoge"]下2つは(:) <$> [1,2] <*> ((:) <$> [3,4] <*> [5,6])などと分解してみると結果の理由が理解しやすい

    ×