少し複雑な関数を書いているとき、$
はよく使われますが、それが何をするのか手がかりがありません。
_$
_は中置「アプリケーション」です。次のように定義されます
_($) :: (a -> b) -> (a -> b)
f $ x = f x
-- or
($) f x = f x
-- or
($) = id
_
余分な括弧を避けるのに役立ちます:f (g x) == f $ g x
。
特に便利な場所は、次のような「末尾のラムダ本体」です
_forM_ [1..10] $ \i -> do
l <- readLine
replicateM_ i $ print l
_
に比べ
_forM_ [1..10] (\i -> do
l <- readLine
replicateM_ i (print l)
)
_
または、「この引数をどんな関数にも適用する」ことを表現するときに、細かく区分されて表示されることがあります
_applyArg :: a -> (a -> b) -> b
applyArg x = ($ x)
>>> map ($ 10) [(+1), (+2), (+3)]
[11, 12, 13]
_
$記号を括弧の代わりとして考えるのが好きです。
たとえば、次の式:
_take 1 $ filter even [1..10]
-- = [2]
_
$を入れないとどうなりますか?その後、我々は得るだろう
_take 1 filter even [1..10]
_
コンパイラーは、take
関数に4つの引数を適用しようとしていると思うので、文句を言うでしょう。引数は_1 :: Int
_、filter :: (a -> Bool) -> [a] -> [a]
、_even :: Integral a => a -> Bool
_、_[1..10] :: [Int]
_。
これは明らかに間違っています。では、代わりに何ができますか?さて、式を括弧で囲むことができます。
_(take 1) (filter even [1..10])
_
これは次のようになります。
_(take 1) ([2,4,6,8,10])
_
その後、次のようになります。
_take 1 [2,4,6,8,10]
_
しかし、特に関数がお互いに入れ子になり始める場合、括弧を常に書きたいとは限りません。別の方法は、括弧のペアが行く場所の間に_$
_記号を置くことです。この場合は次のようになります。
_take 1 $ filter even [1..10]
_