読者です 読者をやめる 読者になる 読者になる

中置演算子に対する部分適用の2パターン

Haskell

HaskellWikiを読んでいたところ、よくわからない例を発見。

Apply a list of functions to a single element to get a list of results.

It's not in the book, but it's easy when you know how:

map ($ my_element) xs

つまり、次のように書くことで、一つの値に対して複数の関数を適用した結果のリストが得られる。

map ($ 1) [sin, cos, tan]
-- => [0.7071067811865475,0.7071067811865476,0.9999999999999999]

どうやら($ 1) ff $ 1と解釈されるらしい(ちなみに$は最も優先順位が低いことから、式の評価順序を制御する区切りとして用いられる。ここではf $ 1 == f 1である)。 実際にGHCiで型を調べてみても、fを受け取って適用する場合の形となっている。

Prelude> :t ($ 1)
($ 1) :: Num a => (a -> b) -> b

どうしてこのように解釈されるのか調べたところ、これはSectionと呼ばれる構文とのこと。

Sectionは次のような糖衣構文であり、それぞれ右辺のように解釈される。ここでop+$などの中置演算子である。

(e op) == \x -> e op x
(op e) == \x -> x op e

累乗演算を例に表すと、下記のようになる。

(2 ^) 10 == 2 ^ 10 == 1024
(^ 2) 10 == 10 ^ 2 == 100

普通の関数の部分適用も似た形をしているため、少しややこしい。 実際、累乗演算子^を前置演算子(^)として書いた場合は、次のようになる。

((^) 2) 10 == (^) 2 10 == 2 ^ 10 == 1024

Sectionがあることで、HaskellではCommon Lisp1+のような関数が自然に書ける。

map ($ 2) [(3+), (3-), (3*), (3/), (/3)]
-- => [5.0,1.0,6.0,1.5,0.6666666666666666]