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?
$
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]
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]