# [Haskell-cafe] Re: Where do I put the seq?

Ryan Ingram ryani.spam at gmail.com
Thu Aug 20 12:56:43 EDT 2009

```On Thu, Aug 20, 2009 at 7:37 AM, David Leimbach<leimy2k at gmail.com> wrote:
> I'm pretty certain that forcing a pattern match via case is what disallows
> the laziness to get out of hand.  The case statement, when evaluated, must
> choose a matched pattern branch, even if it's the only possibility, which
> ends up boiling down to "seq" anyway doesn't it?

Yep, it's basically the same, just prettier, and, in my opinion, more
clearly specifies what it is you are trying to do.

Compare these identical code fragments:

(a) \xs -> (tail xs, xs `seq` empty, head xs)
(b) \(x:xs) -> (xs, empty, x)

Here are the possibilities for input:

(1) input is _|_
(a) (_|_, _|_, _|_)
(b) _|_
(2) input is []
(a) (_|_, empty, _|_)
(b) _|_
(3) input is (x:xs)
(a) (xs, empty, x)
(b) (xs, empty, x)

In the case of lazy I/O, you can sort-of-imagine the _|_ input case as
a value that means "don't know yet"; the computation is incrementally
updated as the input becomes more defined.  It's complicated because
now you have to differentiate "don't know _|_" with "erroneous _|_"
such as the results of case (2).

If it helps you twist your head around it, think of the input to
interact as coming from a big but slow pure function that is computing
the behavior of every atom in the universe and returning what keys on
a keyboard are getting pressed.  So when you pattern match against
that input, you have to wait for the computation to happen; someone
who doesn't type anything is like that function going into an infinite
loop _|_.  But you can't know if it might decide to return a value
(halting problem!) so you keep running it anyways.

> Or is it that case doesn't have to go through as deep an evaluation as seq
> does in some cases?  Does that even make any sense?  :-)

It's the same as seq; both reduce the argument to WHNF which means
that the constructor type ([] vs. (:) is known.

-- ryan
```