技術のメモ箱

Haskell/高階関数

高階関数

引数として関数を取ったり、返り値として関数を返したりできる関数のこと。
例えばmapやfilterは引数で関数とリストを受け取り、リストの各要素に対して関数を実行した結果を返す関数。


畳み込み

2引数関数fと初期アキュームレータzによる右畳み込みがあるとき、
リスト[3,4,5,6]に対して、本質的には以下を行う。

f 3 (f 4(f 5 (f 6 z)))

2引数関数gと初期アキュームレータzによる左畳み込みがあるとき、
リスト[3,4,5,6]に対して、本質的には以下を行う。

g (g (g (g z 3) 4) 5) 6

$関数

$関数は優先順位が低いため、右側の式が評価された後、左側の関数に引数として渡される。
$から行末までを括弧で囲むのと同じ。

f (g x)
f $ g x

関数合成

2つの関数を合成して1つの関数にする。
1引数の関数の呼び出しが続く場合はシンプルに見える。

f (g (h (x)))
(f . g . h) x

カリー化

Haskellのすべての関数は、カリー化された関数である。
カリー化関数は、1つの引数を取り、その次の引数を受け取る関数を返す。

例えば2つの引数を取る関数は、下記のようにも書ける。

add :: Int -> (Int -> Int)
add x y = x + y

下記の2つは同じ。(add 3)の戻り値として関数が返ってきて、その関数に5を渡す。

add 3 5
(add 3) 5

部分適用

部分適用とは、複数の引数を受け取る関数に対して、実際に一部の引数だけ値を渡し、
残りの引数を受け取る関数を生成することをいう。
(add 3)で得られた関数は、部分適用された関数である。

*Main> :t (add 3)
(add 3) :: Int -> Int

中置関数に対しても、セクションという機能を使って部分適用することができる。

*Main> (*10) 2
20

ポイントフリースタイル

関数はカリー化されているので、両側の最後に同じ引数がある場合は省略できる。
下記の2つは同じ。

func xs = map (+1) xs
func = map (+1)

ラムダ式

無名関数。バックスラッシュ(円マーク)を使う。

\引数 -> 式
Prelude> map (\x -> x * x) [1..5]
[1,4,9,16,25]
pagetop