高階関数を実装する
高階関数は関数を引数として受け取ることができるし、返り値として関数を返すこともできる。
関数を受け取ってそれを2回適用する高階関数
applyTwice :: (a -> a) -> a -> a applyTwice f x = f (f x)
実行結果
*Main> applyTwice (+3) 10 16 *Main> applyTwice (++ "HOOOOO") "FOOOO" "FOOOOHOOOOOHOOOOO" *Main> applyTwice ("Strong" ++) "Zero" "StrongStrongZero" *Main> applyTwice (multThree 2 2) 9 144 *Main> applyTwice (3:) [1] [3,3,1]
引数を1つ受け取って1つの値を返す関数を部分適用で作り出し、
それを applyTwice
の1つ目の引数に設定している。
zipWith を実装する
zipWith
は2つのリストを引数に取り、2つのリストの各要素に関数を適用することで、2つのリストを1つに結合する。
よくわからんのでまず関数の型シグネチャを見てみる
*Main> :t zipWith zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
実装
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c] zipWith' _ [] _ = [] -- リスト a が空 zipWith' _ _ [] = [] -- リスト b が空 zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys
実行結果
*Main> zipWith' (+) [1,2,3] [4,5,6] [5,7,9] *Main> zipWith' max [1,2,3] [4,5,6] [4,5,6] *Main> zipWith' (++) ["aa","bb","cc"] ["xx","yy","zz"] ["aaxx","bbyy","cczz"] *Main> zipWith' (*) (replicate 5 2) [1..] [2,4,6,8,10] *Main> zipWith' (zipWith' (*)) [[1,2,3],[3,5,6],[2,3,4]] [[3,2,2],[3,4,5],[5,4,3]] [[3,4,6],[9,20,30],[10,12,12]]
最後のは難しいけど型考えたら「そうかー」となる。
flip を実装する
引数を入れ替えた関数を返すやつらしい
型シグネチャ
*Main> :t flip flip :: (a -> b -> c) -> b -> a -> c
実装
flip' :: (a -> b -> c) -> (b -> a -> c) flip' f = g where g x y = f y x
実装その2
flip' :: (a -> b -> c) -> b -> a -> c flip' f y x = f x y
その2の方がシンプルになっている。関数がカリー化されていることを上手く使っているらしい。
用途がよくわからんので実行してゆく
*Main> zip [1,2,3,4,5] "hello" [(1,'h'),(2,'e'),(3,'l'),(4,'l'),(5,'o')] *Main> flip' zip [1,2,3,4,5] "hello" [('h',1),('e',2),('l',3),('l',4),('o',5)] *Main> zipWith div [2,2..] [10,8,6,4,2] [0,0,0,0,1] *Main> zipWith (flip' div) [2,2..] [10,8,6,4,2] [5,4,3,2,1]
なるほど、そういうことかというのはわかるが使い所が不明
所感
いまいちflipがよくわからん。関数を変形できるところにメリットがあるのか?
偉い人教えてください...

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