This question already has an answer here:
- What does $ mean/do in Haskell? 2 answers
This happens in the situation you want to apply bunch of functions to the same variable, it may look like this:
map (\f->f 4) [odd, even]
but from LYAH using $
make it very neat
map ($ 4) [odd, even]
why does it work. first I type it in ghci like $ 4 odd
, it failed, then I type ($ 4) odd
, which works fine. then I check the type of ($ 4)
using :t
which shows ($ 4) :: Num a => (a -> b) -> b
, odd
is odd :: Integral a => a -> Bool
. It seems make sense, but still not clear to me.
Can anyone explain it clearly, is it another common usage of $
, and is there other more usage of $
.
Anatomy of the operator
The
$
application operator is in the form:It's often seen in situation when you want to avoid a trailing pair of parenthesis:
is equal to:
The magic behind this is simply explained in its fixity declaration:
This means: everything that is after
$
will be grouped into a single entity, just like if they where enclosed in parenthesis.Of course this can be also "nested" like so:
which means:
Application operator as function
Your case is very interesting and, in my experience, not used very often.
Let's analyze this:
We know that
map
's type is:The behavior, if someone forgot, is: take the first argument (a function from
a
tob
) and apply it to everya
in the second argument list, finally return the resulting list.You can see
($ 4)
as "pass 4 as argument to something". Which means that:is the same as:
So:
means:
Why (func $) is not necessary
You could argue that, just like you can do
(/ 4)
and(2 /)
which respectively means "divide something by 4" and "divide 2 by something", you could do($ 4)
and(func $)
and you would be right.In fact:
is the same as:
which is the same as:
But the reality is that:
would be unnecessary, since the first argument of
map
is always applied to each argument to the list, making the above the same as:Infix operators like
*
,++
, or$
typically take two arguments as inWhen one argument is missing, and they are put between parentheses, they instead form a section:
These sections are equivalent to, respectively,
i.e., they stand for the function that maps the "missing argument" to the result. For instance,
Operator
$
is not special in this respect. We havewhich stands for
The first is not very useful, since
(f $)
is\x -> f $ x
which is (eta-)equivalent to justf
(*). The second is instead useful.(*) To be picky,
seq
can distinguish betweenundefined
and(undefined $)
, but this is a minor difference in practice.$ 4 odd
: This won't work because operators must be surrounded by parentheses when not used in infix form. If you were to do($) 4 odd
, this wouldn't work because argument order is incorrect, you want4
to be the second argument. You could write($) odd 4
though.($ 4) odd
: This does work because it's using operator sections, and here the4
is provided as the second argument to$
. It's like(++ "world") "hello "
being the same as"hello " ++ "world"
.When you have
($ 4) :: Num a => (a -> b) -> b
, andodd :: Integral a => a -> Bool
, you just need to line up the types. Since everyIntegral a
is also aNum a
, we can just "upgrade" (constrain) theNum
toIntegral
for this to work:So
a ~ a
andb ~ Bool
, so you can say thatSo applying it to
odd
gives usThis is because
($ 4) odd
is the same asodd $ 4
. Looking at the definition of$
:We can say that
Which evaluates to
False
.