メリークリスマス 🎅
チキン食いました
関数合成
.
関数を使う。
他の関数に渡す関数をその場で作るときに使う。ラムダ式でできるが、関数合成のほうが簡潔に書けるらしい。
*Main> :t (.) (.) :: (b -> c) -> (a -> b) -> a -> c
関数を2つ引数にとって引数を1つとる関数を返す。
例として数のリストの全部を負のリストにする。
ラムダ式
*Main> map (\x -> negate (abs x)) [4,-2,5,1,-7] [-4,-2,-5,-1,-7]
関数合成
*Main> map (negate . abs) [4,-2,5,1,-7] [-4,-2,-5,-1,-7]
関数合成は右結合なので複数の関数を合成できる
*Main> map (\xs -> negate (sum (tail xs))) [[1..5],[3..6],[1..7]] [-14,-15,-27]
関数合成で書く
*Main> map (negate . sum . tail) [[1..5],[3..6],[1..7]] [-14,-15,-27]
リストの要素に tail, sum, negate の順で適用していく。 関数適用で書くと tail に引数が必要になる。
他引数関数の関数合成
複数の引数を取る関数を合成する場合、部分適用して引数を1つとる関数を作る。
*Main> sum (replicate 5 (max 6.7 8.9)) 44.5
この式は次のように書き換えられる
*Main> (sum . replicate 5) (max 6.7 8.9) 44.5
次のように書いてもよい
*Main> sum . replicate 5 $ max 6.7 8.9 44.5
この場合、replicate に 5 を渡して部分適用させている。
*Main> :t replicate replicate :: Int -> a -> [a] *Main> :t replicate 5 replicate 5 :: a -> [a]
括弧だらけの式を関数合成を使って書き直す場合、まず
- 一番内側の関数とその引数を書き出す
- 書き出したものの前に
$
を置く - その前に置かれていた関数から最後の引数を除去
- 間に
.
を置いて合成する
*Main> replicate 2 (product (map (*3) (zipWith max [1,2] [4,5]))) [180,180]
関数合成
*Main> replicate 2 . product . map (*3) $ zipWith max [1,2] [4,5] [180,180]
所感
複数関数合成されている場合、右から読んでいくのが慣れなくてつらい。練習しないと定着しなさそうである。
Haskell の関数合成 | すぐに忘れる脳みそのためのメモ
この記事はとてもわかりやすかった。
そんでもってカリー化と部分適用の素晴らしさを改めて感じた。

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