-XStrict: Why some binders are not made strict?

Ömer Sinan Ağacan omeragacan at gmail.com
Tue Dec 8 01:40:34 UTC 2015

Let's say I have this code:

    zip :: [a] -> [b] -> [(a, b)]
    zip [] [] = []
    zip (x : xs) (y : ys) = (x, y) : zip xs ys

With -XStrict 'x', 'xs', 'y' and 'ys' don't become strict. I'm wondering about
the motivation behind this, I found this interesting. I always thought -XStrict
gives me this guarantee: If I'm using an already-defined variable(bound by a
let or pattern matching) in an expression, I can be sure that the variable
won't be bottom in that expression, because it would be `seq`d before the
expression is evaluated.

So if I have

    case ... of
        D x y -> <body>


    let x = ...
        y = ...
     in <body>

In both cases I was thinking that in <body> 'x' and 'y' can't be bottom(with
-XStrict). This would make -XStrict programs evaluate like they would in a
call-by-value language(even though in the RTS level thunks will be built).
Variables can't range over computations; all binders evaluated strictly etc.

Can anyone tell me about the motivation behind this decision?

I think the wiki page actually conflicts with itself. It says "...
bindings to be
strict by default" but then in "case expressions" sections says

    case x of (a,b) -> rhs

    is interpreted as

    case x of !(a,b) -> rhs

Here bindings 'a' and 'b' are not made strict. I'd expect something like:

    case x of (!a,!b) -> rhs

(Which seems to be invalid Haskell, but same effect could be achieved with `seq
a (seq b rhs)`)


(I also realized that the wiki page doesn't mention bindings in do syntax, is
it because this case is implied by "function definitions"? That is, bangs are
added after do syntax is desugared and so they become strict?)

More information about the ghc-devs mailing list