Znatz
Znatz

Reputation: 1530

What actually $ function does in haskell?

I know

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

Intuitively it seems to me, like to say, 1. $ delays the evaluation of the function to its left 2. evaluates whats to its right 3. feeds the result of its left to its right.

And it makes perfect sense to me when,

ghci> length $ [1..5]
5
ghci> ($) length [1..5]
5

What I do not understand is why,

ghci> ($ [1..5]) length
5

Judging from the type of $, isn't that its (first) argument should be a function ?

Upvotes: 9

Views: 618

Answers (3)

Andrej Bauer
Andrej Bauer

Reputation: 2477

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)).

Upvotes: 16

Scott Olson
Scott Olson

Reputation: 3542

Your question is really about what is called operator sections. With any operator in Haskell (I will use + as an example) you can write something like (+ arg) or (arg +). These are just shorthand syntax for the anonymous functions (\x -> x + arg) and (\x -> arg + x), respectively.

So, the ($ [1..5]) syntax just means (\x -> x $ [1..5]) which is the same as (\x -> x [1..5]) (ie. a function which passes [1..5] to the function passed as its argument).

Upvotes: 10

drquicksilver
drquicksilver

Reputation: 1635

($ [1..5]) is a section. That's a partially applied operator. It's a shorthand for (\f -> f $ [1..5]).

Sections let you supply one argument to a binary operator and produce a function - a function which is waiting for the remaining argument.

Take a look at http://www.haskell.org/haskellwiki/Section_of_an_infix_operator

Upvotes: 6

Related Questions