この章では、ラムダ、高階関数、などを説明しています。
今までは関数の引数を左辺で定義していました。
plusOne x = x + 1
main = do
    print $ plusOne 100
    
    
    101
    
    この引数を右辺で定義することもできます。
plusOne = \ x -> x + 1
main = do
    print $ plusOne 200
    
    
    201
    
    この右辺の式のことをラムダ式と呼びます。\ (バックスラッシュ)がギリシャ文字のラムダλに似ているからです。
型注釈とラムダ式を並べると書式が同じであることがわかります。
plusOne :: Int -> Int
plusOne =  \x -> x + 1
main = do
    print $ plusOne 300
    
    
    301
    
    
    ラムダ式は名前のない関数(無名関数)で、それを変数に束縛していると考えることもできます。
a = \x -> x + 1
main = do
    print $ a 400
    
    
    401
    
    ラムダ式を変数に束縛しないで使うこともできます。
main = do
    print $ (\x -> x + 1) 500
    
    
    501
    
    一度しか使わない関数にわざわざ名前をつけるのが面倒な時、ラムダ式は便利です。
複数の引数を持つ関数は次のように定義できます。
add1 x y = x + y
add2 = \x y -> x + y
add3 = \x -> \y -> x + y
main = do
    print $ add1 100 100
    print $ add2 200 200
    print $ add3 300 300
    
    
    200
    400
    600
    
    実際には、add3が正式な書き方で、add1もadd2も、add3のシンタックスシュガー(糖衣構文)です。糖衣構文とは、複雑な記述を、簡単な記述に置き換える方法です。内部的には複雑な構文が使われています。
引数として関数を受け取ったり、戻り値として関数を返す関数を高階関数と言います。
higher func = func 200 100
add x y = x + y
sub = \x y -> x - y
main = do
    print $ higher add
    print $ higher sub
    
    
    300
    100
    
    上のsubでは変数にラムダ式が束縛され、その変数がhigher関数に渡されています。変数を経由せずに、関数にラムダ式を直接渡すこともできます。
higher func = func 200 100
main = do
    print $ higher $ \x y -> x + y
    print $ higher $ \x y -> x - y
    
    
    300
    100
    
    
    
division x = \y -> x / y
main = do
    let division5 = division 5
    print $ division5 2
    print $ (division 5) 2
    print $ division 5 2
    
    
    2.5
    2.5
    2.5
    
    
    
add  x y =  x + y
add' x   = \y -> x + y
add''    = \x -> \y -> x + y
main = do
    print $ add   20 30
    print $ add'  20 30
    print $ add'' 30 30
    
    
    50
    50
    50
    
    上記のように引数を分割して、関数をネストさせることをカリー化と言います。実際には、Haskellの関数が受け取ることができる引数は一つだけです。複数の引数を受け取った場合は、関数内部で自動的にカリー化が行われています。
add x y = x + y
main = do
    let add20 = add 20
    print $ add20 30
    print $ (add 20) 30
    
    
    50
    50
    50
    
    上記のようにすれば、関数の一部の引数に値を与えておくことができます。
標準ライブラリで定義されている高階関数を紹介します。
第1引数の処理を第2引数のリストに適応した、新しいリストを作ります。同じ処理をするリスト内包表記もあげておきます。
main = do
    print $ map (*2)  [1..5]
    print [x*2 | x <- [1..5]]
    
    
    [2,4,6,8,10]
    [2,4,6,8,10]
    
    第2引数のリストから、第1引数の条件を満たす要素だけの、新しいリストを作ります。同じ処理をするリスト内包表記もあげておきます。
main = do
    print $ filter (<=5) [1..10]
    print $ [x | x <-    [1..10], x <= 5]
    
    
    [1,2,3,4,5]
    [1,2,3,4,5]
    
    
    リストの要素を左から1つずつ処理しながら集計した、新しいリストを作ります。同じ処理をするsum関数もあげておきます。
foldl :: 集計関数 -> 初期値 -> リスト -> 集計結果
    
main = do
    print $ foldl (+) 0 [1..100]
    print $ sum         [1..100]
    
    
    5050
    5050
    
    
    リストの要素を右から1つずつ処理しながら集計した、新しいリストを作ります。foldlと比べてみました。
main = do
    print $ foldr (-) 0 [1..5]
    print $ foldl (-) 0 [1..5]
    
    
    3
    -15