web-dev-qa-db-ja.com

Haskellで$はどういう意味ですか?

少し複雑な関数を書いているとき、$はよく使われますが、それが何をするのか手がかりがありません。

48
Eddie

_$_は中置「アプリケーション」です。次のように定義されます

_($) :: (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]
_
64
J. Abrahamson

$記号を括弧の代わりとして考えるのが好きです。

たとえば、次の式:

_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]_

14
stephen