# 高階実演

```-- 関数を2回適用する
applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)

-- 関数と2つのリストを引数に取り、2つのリストの各要素にその関数を適用し、2つのリストを1つに結合する
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' _ [] _ = []
zipWith' _ _ [] = []
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys

-- 関数を引数に取り、2つの引数を入れ替える
flip' :: (a -> b -> c) -> (b -> a -> c)
flip' f y x = f x y
```

```Main> applyTwice (+3) 10
16
Main> applyTwice (++ " HAHA") "HEY"
"HEY HAHA HAHA"
Main> applyTwice (multThree 2 2) 9
144
Main> applyTwice (3:) [1]
[3,3,1]
Main> zipWith' (+) [4,2,5,6] [2,6,2,3]
[6,8,7,9]
Main> zipWith' max [6,3,2,1] [7,3,1,5]
[7,3,2,5]
Main> zipWith' (++) ["foo ", "bar ", "baz "] ["fighters", "hoppers", "aldrin"]
["foo fighters","bar hoppers","baz aldrin"]
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]]
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]```