haskellのセクションと無名関数と関数名消費

haskellのセクションと無名関数と関数名消費


通常2引数(?)の関数を1引数の関数にするには関数名を消費する以下のような場合

*Main> let f x=x+1 in f 2
3
*Main> let f x=1+x in f 2
3

これだと定義と本体と二つに分かれるのであまり好きじゃなく、つい数年前から関数型に入り始めた自分としてはつい無名関数を使ってしまっていた。

*Main> (\x->x+1) 2
3
*Main> (\x->1+x) 2
3

どうしても括弧だらけになってしまうんだよな。あとλが入れ子になってしまう。
あとhaskellにはセクションという表現方法がある。

*Main> (+1) 2
3
*Main> (1+) 2
3

これが一番記述量が短い。
でも、これって中置関数でしか使えない。

*Main> elem 1 [1,2,3]
True
*Main> (elem 1)  [1,2,3]
True

最終引数のみならセクションっぽいんだけど 第1引数を引数とする関数がつくれない。

*Main> (elem [1,2,3]) 1

<interactive>:1:15:
    No instance for (Num [[t]])
      arising from the literal `1' at <interactive>:1:15
    Possible fix: add an instance declaration for (Num [[t]])
    In the first argument of `(elem [1, 2, 3])', namely `1'
    In the expression: (elem [1, 2, 3]) 1
    In the definition of `it': it = (elem [1, 2, 3]) 1

そりゃそうだわな。

そこで関数をバッククオートで囲って中置化すると

*Main> 1 `elem` [1,2,3]
True

これをセクションにすると

*Main> (`elem` [1,2,3]) 1
True

おお、意味も第1引数が左側に来るのがわかるのでわかりやすい。

じゃ、長さを比較する

*Main> let f x=elem x [1,2,3] in f 1
True
*Main> (\x->elem x [1,2,3]) 1
True
*Main> (`elem` [1,2,3]) 1
True

となりもっとも短くなる。xを書かない文わかりやすいんじゃないだろうか?
まあ、もちろん2項演算しかできなさそうだけど…

たぶんこれをカリー化って言うんだろう…

追記 2010/09/01 10:08:38:

flipを使えば第1引数と第2引数を入れ替えられる。けど長さは中置の方がみじかい

*Main> (flip elem [1,2,3]) 1
True
*Main> (`elem` [1,2,3]) 1
True