home


[高階関数]

高階関数とは,引数として関数を受け取ったり,返り値として関数を返すような関数のことです.

1. 引数に関数をとる関数

高階関数の例として,まず引数に関数をとる関数を見てみることにします. 以下に定義するsigma123は,「実数を引数として受け取り実数を返す関数f」を引数として受け取り,その関数に1.0,2.0.3.0を代入した結果の和を返す,高階関数の例です.以下ではsigma123の動作確認の為,ついでに「引数の値を1.0増やす関数inc」や,「逆数をとる関数inv」を定義しています.(プログラム中で"--"以降はコメントとして扱われます)
sigma123::(Double->Double)->Double
sigma123 f = (f 1.0) + (f 2.0) + (f 3.0) -- f(1.0)+f(2.0)+f(3.0)

inc x = x + 1.0
inv x = 1.0 / x
sigma123にincやinvを渡してみると,以下のようになります.
*Main> sigma123 inc
9.0
*Main> sigma123 inv
1.8333333333333333

2. 無名関数

Haskellでは名前を付けることなく関数を定義することが出来ます. これには"\"の後に引数を並べて書き,"->" の後に関数の本体を書きます. 例えば3つの引数x,y,zを受け取り,その和を返す無名関数は"\ x y z -> x + y + z"のように表記することが出来ます. これに引数1,2,3を渡してみると,以下のようになります.
*Main> (\ x y z -> x + y + z) 1 2 3
6

3. 関数を返り値とする関数

無名関数を用いて,関数を返り値として返す関数を定義することが出来ます. 例として,以下のcomposeは引数として2つの「実数を引数として受け取り実数を返す関数」fおよびgを受け取り,fとgを合成した関数を返します.fとgの合成関数とは,引数xに対しg(f(x))を返す関数のことです.
compose::(Double->Double)->(Double->Double)->(Double->Double)
compose f g = \ x -> g(f(x))
先ほど定義したincとinvをcomposeに渡してみます.incとinvの適用順序に注意してみてください.
*Main> (compose inc inv) 2.0 -- 1.0/(2.0+1.0)
0.3333333333333333
*Main> (compose inv inc) 2.0 -- 1.0+(1.0/2.0)
1.5
上で定義したcomposeと同じことは,実は備え付けの"."演算子を用いて行うことが出来ます.演算子は引数が1つまたは2つの(高階)関数に過ぎません.
*Main> (inv . inc) 2.0
0.3333333333333333
*Main> (inc . inv) 2.0
1.5
他の例として,以下のfixFirstArgは引数として「2つの引数を受け取る関数f」と「値a」を受け取り,fの最初の引数をaに固定した1引数の関数を返します.動作確認用に2引数の関数gも定義しています.
fixFirstArg f a = \b -> f a b

g x y = x + y + 3
動作例は以下のようになります.
*Main> (fixFirstArg g 2.0) 1.0
6.0
Haskellでは関数の引数の一部のみを適用し残りの引数からなる関数を得る部分適用が備え付けの機能として用意されていて,上記と同じことを以下のように簡潔に行うことが出来ます.
*Main> (g 2.0) 1.0
6.0