fugafuga.write

日々のログ

すごいH本 part74

IOはアプリカティブファンクター

IO は Applicative

instance Applicative IO where
    pure  = return
    a <*> b = do
        f <- a
        x <- b
        return (f x)

return は何もしない I/Oアクションを返す。

IOに関する <*> 演算子は、 2つのI/O アクションを1つに糊付けするにあたって逐次実行という意味が加わっている。

myAction :: IO String
myAction = do
    a <- getLine
    b <- getLine
    return $ a ++ b

これをアプリカティブスタイルで書ける。

myAction :: IO String
myAction = (++) <$> getLine <*> getLine

getLine は実世界から文字列をとってきてくれる小さな箱。

(++) <$> getLine <*> getLine は、 小さな箱を2つ実世界に送り出して端末から入力行を取得し、 結合して返してくれる大きな箱が作られる。

つまり、式 (++) <$> getLine <*> getLine は I/O アクションである。

よって、このように書くことができる。

main = do
    a <- (++) <$> getLine <*> getLine
    putStrLn $ "The two lines concatenated turn out to be: " ++ a

関数もアプリカティブファンクター

関数 (->) r

instance Applicative ((->) r) where
    pure x = (\_ -> x)
    f <*> g = \x -> f x (g x)

pure は、引数を無視して常にその値を返す関数 を作る。

*Main> :t (+) <$> (+3) <*> (*100)
(+) <$> (+3) <*> (*100) :: Num b => b -> b
*Main> (+) <$> (+3) <*> (*100) $ 5
508

引数を (+3)(*100) に渡し、+ を使う関数ができる。

所感

関数のアプリカティブファンクターの処理順が、<*><$> の順番になるのは何故なんだろうか。

すごいHaskellたのしく学ぼう!

すごいHaskellたのしく学ぼう!

  • 作者: MiranLipovaca
  • 出版社/メーカー: オーム社
  • 発売日: 2017/07/14
  • メディア: Kindle版
  • 購入: 4人 クリック: 9回
  • この商品を含むブログを見る