This has to do with parsing. In Haskell you can write (op arg)
where op
is an infix operator. This is not the same as ((op) arg)
. And you can write (arg op)
as well! For example:
GHCi, version 7.0.3: http://www.haskell.org/ghc/ :? for help
Prelude> :t (+ 4)
(+ 4) :: Num a => a -> a
Prelude> :t (4 +)
(4 +) :: Num a => a -> a
That is, (+ 4)
is the function \x -> x + 4
and (4 +)
is the function \y -> 4 + y
. In the case of addition these are equal functions, but that is not really important right now.
Now let us try the same trick on $
:
Prelude> :t ($ [1,2,3,4])
($ [1,2,3,4]) :: Num t => ([t] -> b) -> b
Now surprise so far, we got \f -> f $ [1,2,3,4]
. We can also write
Prelude> :t (length $)
(length $) :: [a] -> Int
to get the function \l -> length $ l
. But how about this:
Prelude> :t ($ length)
($ length) :: (([a] -> Int) -> b) -> b
This is strange, but it makes sense! We got \f -> f $ length
, i.e., a functional which expects to get a function f
of type ([a] -> Int) -> b)
that will be applied to length
. There is a fourth possibility:
Prelude> :t ([1,2,3,4] $)
<interactive>:1:2:
Couldn't match expected type `a0 -> b0' with actual type `[t0]'
In the first argument of `($)', namely `[1, 2, 3, 4]'
In the expression: ([1, 2, 3, 4] $)
Everything is as it should be because [1,2,3,4]
is not a function. What if we write $
in parenthesis? Then its special meaning as an infix operator disappears:
Prelude> :t (($) length)
(($) length) :: [a] -> Int
Prelude> :t (($) [1,2,3,4])
<interactive>:1:6:
Couldn't match expected type `a0 -> b0' with actual type `[t0]'
In the first argument of `($)', namely `[1, 2, 3, 4]'
In the expression: (($) [1, 2, 3, 4])
Prelude> :t (length ($))
<interactive>:1:9:
Couldn't match expected type `[a0]'
with actual type `(a1 -> b0) -> a1 -> b0'
In the first argument of `length', namely `($)'
In the expression: (length ($))
Prelude> :t ([1,2,3,4] ($))
<interactive>:1:2:
The function `[1, 2, 3, 4]' is applied to one argument,
but its type `[t0]' has none
In the expression: ([1, 2, 3, 4] ($))
So, to answer your question: $ [1,2,3,4]
is parsed as \f -> f $ [1,2,3,4]
so it makes perfect sense to apply it to length
. However ($) [1, 2, 3, 4]
does not make much sense because ($)
is not seen as an infix operator.
By the way, $
does "not do anything", so to speak. It is mostly used for more readable input because it has low precedence and so we can write f $ g $ h $ x
instead of f (g (h x))
.
($)
, but about operator sections. – Inwardness$
doesn't delay evaluation of the function to it's left. You may be confusing it with$!
, which forces partial evaluation of the argument to its right before feeding it to the function to its left. – Hendricksmap ($ [1..5]) [length,sum,product]
. – Inwardnessid $! x == x `seq` id x
doesn't force anything, or so I've been told. – Randeeseq
, or($!)
are only evaluated when their result is demanded. Since argument and result ofid
are the same,id $! x
forces the evaluation of the argument,x
, (to weak head normal form) exactly when the result,x
, needs to be evaluated (to WHNF). So it's rather hard to determine whether the($!)
did anything there. But in an implementation wherea `seq` b
evaluatesa
beforeb
(that is not required by the semantics ofseq
), if you look hard enough, you can see thatid $! undefined
errors beforeid
returns. </pointless pedanticism> – Messere$!
"forces its argument". The real question, when?, is left out by this magical statement. Would it be better to say that$!
"arranges for its argument to be forced before being fed to the function, when the result of function application is forced"? – Randee($!)
forces its second argument when its result is needed to be evaluated. – Messere