haskell $ 演算子の挙動
プログラミング言語 Haskell における演算子$
に関するメモ。
次の関数 は指定範囲の数列のうちの偶数の二乗の総和を求める関数である。
f x y = sum $ map (^2) $ filter even [x..y] g x y | x < y = f x y | x > y = f y x main = print $ g 1 10
これは次のコードと等価である。
f x y = ((sum) (map (^2) (filter even [x..y]))) g x y | x < y = f x y | x > y = f y x main = print $ g 1 10
$
は以下の実行結果が示すように GHC.Base モジュールで定義されている。
Prelude> :i ($) ($) :: forall (r :: GHC.Types.RuntimeRep) a (b :: TYPE r). (a -> b) -> a -> b -- Defined in ‘GHC.Base’ infixr 0 $
infixr 0 $, $! --- 略 {-# INLINE ($) #-} ($) :: forall r a (b :: TYPE r). (a -> b) -> a -> b f $ x = f x
上記定義の通り、$
演算子は関数とその引数を受け取りその引数を関数に転送する。また優先レベルは 0 であり右に結合する。以上の定義を参考に次のコードの評価順序を順にシミュレートする。
f x y = sum $ map (^2) $ filter even [x..y]
$
は優先順位が最も低いので以下のように括弧がつく。
f x y = (sum) $ (map (^2)) $ (filter even [x..y])
$
は右に結合するので以下のように括弧がつく。
f x y = (sum) $ ((map (^2)) $ (filter even [x..y]))
$
を消去して以下の式に納まる。
f x y = ((sum) ((map (^2)) (filter even [x..y])))
*1:https://github.com/ghc/ghc/blob/a67c264201a5d73d3624a73359f36adfaf6ec33c/libraries/base/GHC/Base.hs#L146
*2:https://github.com/ghc/ghc/blob/a67c264201a5d73d3624a73359f36adfaf6ec33c/libraries/base/GHC/Base.hs#L1322-L1324
*3:The Haskell 2010 Language/4.4.2 Fixity Declarations, Haskell 98 Language and Libraries The Revised Report/4.4.2 Fixity Declarations で $ 演算子の優先順位は最低となっている。