Haskell 勉強メモ8

高階関数

Haskell は関数を引数にとったり、返り値として関数を返すことができる。このような関数を高階関数と呼ぶ。Scalaにもある。

カリー化関数

Haskellの全ての関数は、引数を1つだけ取る。今まで、複数引数を取っているように見えたものは全てカリー化された関数だ。

Prelude> :t max
max :: Ord a => a -> a -> a

Prelude> max 4 5
5

max 関数は2つの引数を取り、大きい方を返す関数のように見えるが実際はカリー化された関数。まず、max 4 が適用され、max 4 は1つの値を引数にとる別の関数を返す。返ってきた関数に対して、5が適用されるという流れだ。

Prelude> let max' = max 4
Prelude> :t max'
max' :: (Ord a, Num a) => a -> a
Prelude> 

Scalaもカリー化できる。

def max(a: Int)(b: Int): Int = if (a >= b) a else b

max(4)(5) val res0: Int = 5
val max2 = max(4)(_) // val max2: Int => Int = <function>

Scalaの場合はHaskellほど素直ではなく、適用しない部分には _ を入れる必要があるようだ。また、関数部分適用はカリー化されていなくてもできて

def multiThree(x: Int, y: Int, z: Int): Int = x * y * z

val m2 = multiThree(3, _, _) // val m2: (Int, Int) => Int = <function>
m2(2, 4) // val res2: Int = 24

のように書くこともできる。

今度は、Int を引数にとって100と比較する関数を作る。これは単純に書くとこうだが

compareWithHundred :: Int -> Ordering
compareWithHundred x = compare 100 x

*Main> compareWithHundred 99
GT

実際には下記のように書くことができる

compareWithHundred :: Int -> Ordering
compareWithHundred = compare 100

compare 100 が引数を一つとって、Ordering を返す関数であるからだ。