tags:

views:

229

answers:

2

Can anybody explain the difference in Haskell between the operators ($) and ($!) (dollar sign vs dollar sign exclamation point)?

I haven't seen the use of $! anywhere so far, but while browsing through the Haskell reference on www.zvon.org, I noticed its existence and that it has the exact same definition as $. When trying some simple statements in a Haskell interpreter (ghci), I couldn't find any difference, nor could I find any reference to the operator in the top listed tutorials when googling for haskell tutorial.

So, just out of curiosity, what is the difference, if at all?

+14  A: 

($!) is strict function application. That is, it evaluates the argument before evaluating the function.

This is contrary to normal lazy function application in Haskell, e.g. f x or f $ x, which first start to evaluate the function f, and only compute the argument x if it is needed.

For example succ (1 + 2) will delay the addition 1 + 2 by creating a thunk, and start to evaluate succ first. Only if the argument to succ is needed, will 1 + 2 be evaluated.

However, if you know for sure that the argument to a function will always be needed, you can use ($!), which will first evaluate the argument to weak head normal form, and then enter the function. This way, you don't create a whole big pile of thunks and this can be more efficient. In this example, succ $! 1 + 2 would first compute 3 and then enter the function succ.

Note that it is not always safe to just replace normal function application with strict function application. For example:

ghci> const 1 (error "noo!")
1
ghci> const 1 $! (error "noo!")
*** Exception: noo!
Tom Lokhorst
Last example is more about side effect of `error`. Functional semantic should never be hurt by bangs (the same for `par` and `seq`). Putting bangs may sometimes increase speed/memory and sometimes decrease. And in some special cases it can lead to never-ending calculations `const 1 $! (last [1..])`.
ony
Well, the printing of the message is a side effect, but the point is that `error` is ⊥ (bottom). Just like a never-ending calculation is ⊥. If you evaluate ⊥ using a `seq`, the semantics of your program change. This is why you should be careful with things like `seq` and `($!)`, it can increase (or decrease) the efficiency of you program, but it could also potentially make it crash where it normally shouldn't have.
Tom Lokhorst
+5  A: 

See the seq function, which forces the evaluation of a value. $! is defined in terms of seq.

This is a blog post which shows some nuances of its use.

Francesco
Ah, stupid me! It says so on zvon as well in the description of `$!`, but for some reason the equals sign never rang a bell...Thanks for the link to the blog.
Jelle Fresen