32

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, 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 searching for haskell tutorial.

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

Bleeding Fingers
  • 6,993
  • 7
  • 46
  • 74
Jelle Fresen
  • 1,916
  • 1
  • 20
  • 24

2 Answers2

48

($!) 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
  • 13,658
  • 5
  • 55
  • 71
  • 4
    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 May 09 '10 at 12:47
  • 9
    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 May 09 '10 at 19:19
7

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
  • 3,200
  • 1
  • 34
  • 46
  • 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 May 07 '10 at 10:07
  • 1
    `f $! x = x ``seq`` f x` http://hackage.haskell.org/packages/archive/base/latest/doc/html/src/Prelude.html#%24%21 –  Aug 03 '11 at 21:02