2

Given the data type, Foo:

Prelude> data Foo a = Foo a

It does not implement Show, so it can't be printed.

Prelude> Foo 5
<interactive>:13:1:
    No instance for (Show (Foo a0)) arising from a use of ‘print’

However, given a function that always throws:

Prelude> let f _ = error("bad!")

f can be applied to it.

Prelude> f (Foo 5)
*** Exception: bad!

Since f always throws for its single argument, does that mean that its argument is never evaluated, not even to Weak Head Normal Form?

Kevin Meredith
  • 41,036
  • 63
  • 209
  • 384

3 Answers3

4

The function "f" never evaluates its argument, as you say. This has nothing to do with whether the argument is an instance of "Show".

You could also say

Prelude> let f2 _ = "Some value"

Prelude> f2 (Foo 5)
"Some value"

But the real point is that even if the argument to f2 is undefined it will not be evaluated, and so will not throw an exception

Prelude> f2 undefined
"Some value"
Paul Johnson
  • 17,438
  • 3
  • 42
  • 59
3

No, the argument of f is not evaluated. An easy way to test this is to use undefined, which will throw an error as soon as it's touched:

>>> undefined
*** Exception: Prelude.undefined

>>> let f _ = "bad"

>>> f undefined
"bad"

but you can write a similar function that does evaluate its argument to WHNF using seq:

>>> let g a = a `seq` "bad"
>>> g undefined
"*** Exception: Prelude.undefined

or BangPatterns:

>>> :set -XBangPatterns 
>>> let h !_ = "bad"
>>> h undefined 
"*** Exception: Prelude.undefined

or pattern match:

>>> let k (Foo _) = "bad"
>>> k undefined 
"*** Exception: Prelude.undefined

but you can do a lazy pattern match using ~:

>>> let j ~(Foo _) = "bad"
>>> j undefined 
"bad"
cchalmers
  • 2,896
  • 1
  • 11
  • 11
  • 2
    Due to the [nature of imprecise exceptions](http://stackoverflow.com/q/11070690/791604), seeing that `f undefined` throws a different error than `undefined` is _not_ good evidence that `f` is lazy. Even with `f x = x \`seq\` error "bad"`, a compiler is allowed to throw the "bad" exception instead of the one you get from `x` -- in a pinch, any old exception you have lying around will do. – Daniel Wagner Sep 06 '15 at 12:44
  • Thanks, I've changed it to just return the string "bad". – cchalmers Sep 06 '15 at 17:43
1
Prelude> let f _ = error("bad!")

Haskell is lazy, the _param is not evaluated at all.

The slogan to remember is “pattern matching drives evaluation”. To reiterate the important points:

Expressions are only evaluated when pattern-matched

…only as far as necessary for the match to proceed, and no farther!
Kamel
  • 1,856
  • 1
  • 15
  • 25