アプリカティブの便利な関数
Control.Applicative
にliftA2
という関数がある。
liftA2 :: (Applicative f) => (a -> b -> c) -> f a -> f b -> f c liftA2 f a b = f <$> a <*> b
1つの関数を2つのアプリカティブ値に適用する関数。 これを、
liftA2 :: (Applicative f) => (a -> b -> c) -> (f a -> f b -> f c)
のように解釈すると、
通常の2引数関数を、2つのアプリカティブ値を引数に取る関数に昇格させる
関数
とみなすことができる。
2つのアプリカティブ値からそれらの返り値をリストとして内包する1つのアプリカティブ値を組み立てることができる。
Just 3
と Just 4
を使って実践する。
まず、Just 4
を Just [4]
にする。
*Main Control.Applicative> fmap (\x -> [x]) (Just 4) Just [4]
Just [3,4]
を作る
*Main Control.Applicative> liftA2 (:) (Just 3) (Just [4]) Just [3,4]
これと同じ
*Main Control.Applicative> (:) <$> (Just 3) <*> (Just [4]) Just [3,4]
アプリカティブ値のリストをとって、 リストを返り値として持つ1つのアプリカティブ値を返す関数を作る
sequenceA' :: (Applicative f) => [f a] -> f [a] sequenceA' [] = pure [] sequenceA' (x:xs) = (:) <$> x <*> sequenceA' xs
実行
*Main Control.Applicative> sequenceA' [Just 1, Just 2] Just [1,2]
こう書くのと同値
*Main Control.Applicative> (:) <$> Just 1 <*> sequenceA' [Just 2] Just [1,2]
さらに評価を進めるとこう
*Main Control.Applicative> (:) <$> Just 1 <*> ((:) <$> Just 2 <*> sequenceA' []) Just [1,2]
sequenceA' []
は Just []
になる
*Main Control.Applicative> (:) <$> Just 1 <*> ((:) <$> Just 2 <*> Just []) Just [1,2]
最終的にこう
*Main Control.Applicative> (:) <$> Just 1 <*> Just [2] Just [1,2]
sequenceA' は畳み込みを使っても実装できる
sequenceA'' :: (Applicative f) => [f a] -> f [a] sequenceA'' = foldr (liftA2 (:)) (pure [])
実行
*Main Control.Applicative> sequenceA'' [Just 3, Just 2, Just 1] Just [3,2,1] *Main Control.Applicative> sequenceA'' [Just 3, Nothing, Just 1] Nothing *Main Control.Applicative> sequenceA'' [(+3),(+2),(+1)] 3 [6,5,4] *Main Control.Applicative> sequenceA'' [[1,2,3],[4,5,6]] [[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]] *Main Control.Applicative> sequenceA'' [[1,2,3],[4,5,6],[3,4,4],[]] []
Maybe 値のリストに対して使うと、すべての返り値をリストとして含んだ単一のMaybe値ができる。 ただし、元のリストの中のMaybe値のいずれかがNothingだった場合、結果もNothingになる。
これを使う場面として、 Maybe値のリストがあり、要素のすべてがNothingでない場合に限ってなにかしたい場合に使う。
*Main Control.Applicative> map (\f -> f 7) [(>4),(<10),odd] [True,True,True] *Main Control.Applicative> and $ map (\f -> f 7) [(>4),(<10),odd] True
sequenceA'' を使う
*Main Control.Applicative> sequenceA'' [(>4),(<10),odd] 7 [True,True,True] *Main Control.Applicative> and $ sequenceA'' [(>4),(<10),odd] 7 True
sequenceA を []
に対して使うと、リストのリストをとり、リストのリストを返す関数になる。
*Main Control.Applicative> sequenceA [[1,2,3],[4,5,6]] [[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]] *Main Control.Applicative> [[x,y] | x <- [1,2,3], y <- [4,5,6]] [[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]]
I/O アクションに対して使う
*Main Control.Applicative> sequenceA [getLine, getLine, getLine] hey foo hoo ["hey","foo","hoo"]
所感
最後の方が難しい。理解しきれてない部分がある。

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