From what I'm reading, $ is described as "applies a function to its arguments." However, it doesn't seem to work quite like (apply ...) in Lisp, because it's a binary operator, so really the only thing it looks like it does is help to avoid parentheses sometimes, like foo $ bar quux
instead of foo (bar quux)
. Am I understanding it right? Is the latter form considered "bad style"?
-
You're mostly understanding it right---that is, about 99% of the use of $ is to help avoid parentheses, and yes, it does appear to be preferred to parentheses in most cases.
Note, though:
> :t ($) ($) :: (a -> b) -> a -> b
That is, $ is a function; as such, it can be passed to functions, composed with, and anything else you want to do with it. I think I've seen it used by people screwing with combinators before.
-
$
is preferred to parentheses when the distance between the opening and closing parens would otherwise be greater than good readability warrants, or if you have several layers of nested parentheses.For example
i (h (g (f x)))
can be rewritten
i $ h $ g $ f x
In other words, it represents right-associative function application. This is useful because ordinary function application associates to the left, i.e. the following
i h g f x
...can be rewritten as follows
(((i h) g) f) x
Other handy uses of the
($)
function include zipping a list with it:zipWith ($) fs xs
This applies each function in a list of functions
fs
to a corresponding argument in the listxs
, and collects the results in a list. Contrast withsequence fs x
which applies a list of functionsfs
to a single argumentx
and collects the results; andfs <*> xs
which applies each function in the listfs
to every element of the listxs
.Paul Johnson : A useful point about the daisy chain of $ signs is that it can be read a bit like a Unix pipeline, only going from right to left.Apocalisp : It can be read "a bit" like that, which is why it's best not to think of it that way. -
The documentation of ($) answers your question. Unfortunately it isn't listed in the automatically generated documentation of the Prelude.
However it is listed in the sourcecode which you can find here:
http://darcs.haskell.org/packages/base/Prelude.hs
However this module doesn't define ($) directly. The following, which is imported by the former, does:
http://darcs.haskell.org/packages/base/GHC/Base.lhs
I included the relevant code below:
infixr 0 $ ... -- | Application operator. This operator is redundant, since ordinary -- application @(f x)@ means the same as @(f '$' x)@. However, '$' has -- low, right-associative binding precedence, so it sometimes allows -- parentheses to be omitted; for example: -- -- > f $ g $ h x = f (g (h x)) -- -- It is also useful in higher-order situations, such as @'map' ('$' 0) xs@, -- or @'Data.List.zipWith' ('$') fs xs@. {-# INLINE ($) #-} ($) :: (a -> b) -> a -> b f $ x = f x
-
Lots of good answers above, but one omission:
$
cannot always be replace by parenthesesBut any application of
$
can be eliminated by using parentheses, and any use of($)
can be replaced byid
, since$
is a specialization of the identity function. Uses of(f$)
can be replaced byf
, but a use like($x)
(take a function as argument and apply it tox
) don't have any obvious replacement that I see.Martijn : ($ x) is easily replaced by (\f -> f x) -
If I look at your question and the answers here, Apocalisp and you are both right:
$
is preferred to parentheses under certain circumstances (see his answer)foo (bar quux)
is certainly not bad style!
Also, please check out difference between . (dot) and $ (dollar sign), another SO question very much related to yours.
0 comments:
Post a Comment