web-dev-qa-db-fra.com

Que signifie $ / faire à Haskell?

Lorsque vous écrivez des fonctions légèrement plus complexes, je remarque que $ est beaucoup utilisé mais je n'ai aucune idée de ce qu'il fait?

48
Eddie

$ Est l'infixe "application". Il est défini comme

($) :: (a -> b) -> (a -> b)
f $ x = f x

-- or 
($) f x = f x
-- or
($) = id

C'est utile pour éviter les parenthèses supplémentaires: f (g x) == f $ g x.

Un emplacement particulièrement utile pour cela est pour un "corps lambda traînant" comme

forM_ [1..10] $ \i -> do
  l <- readLine
  replicateM_ i $ print l

par rapport à

forM_ [1..10] (\i -> do
  l <- readLine
  replicateM_ i (print l)
)

Ou, délicatement, il apparaît parfois en section lors de l'expression "appliquer cet argument à n'importe quelle fonction"

applyArg :: a -> (a -> b) -> b
applyArg x = ($ x)

>>> map ($ 10) [(+1), (+2), (+3)]
[11, 12, 13]
64
J. Abrahamson

J'aime à penser que le signe $ remplace la parenthèse.

Par exemple, l'expression suivante:

take 1 $ filter even [1..10] 
-- = [2]

Que se passe-t-il si nous ne mettons pas le $? Ensuite, nous aurions

take 1 filter even [1..10]

et le compilateur se plaindrait maintenant, car il penserait que nous essayons d'appliquer 4 arguments à la fonction take, les arguments étant 1 :: Int, filter :: (a -> Bool) -> [a] -> [a], even :: Integral a => a -> Bool, [1..10] :: [Int].

C'est évidemment incorrect. Alors, que pouvons-nous faire à la place? Eh bien, nous pourrions mettre des parenthèses autour de notre expression:

(take 1) (filter even [1..10])

Cela se résumerait désormais à:

(take 1) ([2,4,6,8,10])

qui devient alors:

take 1 [2,4,6,8,10]

Mais nous ne voulons pas toujours écrire des parenthèses, en particulier lorsque les fonctions commencent à être imbriquées les unes dans les autres. Une alternative est de placer le signe $ Entre où irait la paire de parenthèses, qui dans ce cas serait:

take 1 $ filter even [1..10]

14
stephen