Understanding strictness of ghc output

Hello, I'm trying to figure out how you tell if ghc has correctly infered strictness or whether or not a little more prompting from me is needed. I tried compiling with -ddump-simpl, and I guess from looking at this the DmdType bit is what I want (maybe). So if I have "DmdType LS" for a function of arity 2, does this mean the function is lazy in the first argument and strict in the second? I would be pretty confident that this was the correct interpretation, but this is the Haskell code (from AVL library).. height :: AVL e -> Int height = addHeight 0 where addHeight h E = h addHeight h (N l _ _) = addHeight h+2 l addHeight h (Z l _ _) = addHeight h+1 l addHeight h (P _ _ r) = addHeight h+2 r It seems pretty obvious to me that addHeight is strict in its first argument if + is strict for Ints (as I guess it is). But this gives "DmdType LS". Even if I rewrite it.. height :: AVL e -> Int height = addHeight 0 where addHeight h E = h addHeight h (N l _ _) = let h' = h+2 in h' `seq` addHeight h' l addHeight h (Z l _ _) = let h' = h+1 in h' `seq` addHeight h' l addHeight h (P _ _ r) = let h' = h+2 in h' `seq` addHeight h' r .. it still gives "DmdType LS". So does this.. height :: AVL e -> Int height = addHeight 0 where addHeight h E = h addHeight h (N l _ _) = h `seq` addHeight (h+2) l addHeight h (Z l _ _) = h `seq` addHeight (h+1) l addHeight h (P _ _ r) = h `seq` addHeight (h+2) r So am I interpreting core correctly? Thanks -- Adrian Hey

Adrian Hey
height :: AVL e -> Int height = addHeight 0 where addHeight h E = h addHeight h (N l _ _) = addHeight h+2 l addHeight h (Z l _ _) = addHeight h+1 l addHeight h (P _ _ r) = addHeight h+2 r
It seems pretty obvious to me that addHeight is strict in its first argument if + is strict for Ints (as I guess it is).
No, this looks very obviously lazy to me. The first argument is always a pattern variable, h, and therefore no evaluation is required on it - the value is just bound lazily and used on the RHS.
height :: AVL e -> Int height = addHeight 0 where addHeight h E = h addHeight h (N l _ _) = let h' = h+2 in h' `seq` addHeight h' l addHeight h (Z l _ _) = let h' = h+1 in h' `seq` addHeight h' l addHeight h (P _ _ r) = let h' = h+2 in h' `seq` addHeight h' r
.. it still gives "DmdType LS".
Even though many uses of 'h' are strictified, the first clause addHeight h E = h is still lazy, because it simply binds the variable without forcing it.
height :: AVL e -> Int height = addHeight 0 where addHeight h E = h addHeight h (N l _ _) = h `seq` addHeight (h+2) l addHeight h (Z l _ _) = h `seq` addHeight (h+1) l addHeight h (P _ _ r) = h `seq` addHeight (h+2) r
Same again. Try addHeight h E = h `seq` h which, although it looks bizarre, actually forces the evaluation of h, whilst simply returning it does not. Regards, Malcolm

On Tue, Jun 22, 2004 at 01:52:44PM +0100, Malcolm Wallace wrote:
Adrian Hey
writes: [...] the first clause addHeight h E = h is still lazy, because it simply binds the variable without forcing it.
Since addHeight _|_ E -> _|_, this is strict in the first argument. I do not know, what the strictness analyzer makes of it, though. Greetings, Carsten -- Carsten Schultz (2:38, 33:47), FB Mathematik, FU Berlin http://carsten.codimi.de/ PGP/GPG key on the pgp.net key servers, fingerprint on my home page.

On Tue, Jun 22, 2004 at 01:52:44PM +0100, Malcolm Wallace wrote:
Same again. Try addHeight h E = h `seq` h
which, although it looks bizarre, actually forces the evaluation of h, whilst simply returning it does not.
That contradicts my intution for seq. I would read it as "h is forced before h is forced", and I would think that (h `seq` h) is equivalent to h. Were I am wrong? Best regards, Tom -- .signature: Too many levels of symbolic links

On Tue, 2004-06-22 at 14:17, Tomasz Zielonka wrote:
On Tue, Jun 22, 2004 at 01:52:44PM +0100, Malcolm Wallace wrote:
Same again. Try addHeight h E = h `seq` h
which, although it looks bizarre, actually forces the evaluation of h, whilst simply returning it does not.
That contradicts my intution for seq. I would read it as "h is forced before h is forced", and I would think that (h `seq` h) is equivalent to h.
I think a better intuition is that "h is forced before h is *returned*". You can return a value without that value being forced to head normal form. In fact this is the ordinary case. Values are only 'forced' when you pattern match on them (or if you use seq), and even then only when the result of the pattern match is used. Duncan

Duncan Coutts wrote:
On Tue, 2004-06-22 at 14:17, Tomasz Zielonka wrote:
On Tue, Jun 22, 2004 at 01:52:44PM +0100, Malcolm Wallace wrote:
Same again. Try addHeight h E = h `seq` h
which, although it looks bizarre, actually forces the evaluation of h, whilst simply returning it does not.
That contradicts my intution for seq. I would read it as "h is forced before h is forced", and I would think that (h `seq` h) is equivalent to h.
I think a better intuition is that "h is forced before h is *returned*". You can return a value without that value being forced to head normal form. In fact this is the ordinary case. Values are only 'forced' when you pattern match on them (or if you use seq), and even then only when the result of the pattern match is used.
However, standard lazy evaluation will only evaluate a function application if the head normal form of the result is needed. So when addHeight is computed its result is needed. Hence there is no point in writing "h `seq` h" instead of just "h". This could only make a difference for some form of optimistic evaluator that stops in the middle of evaluation on turns the remaining evaluation into a closure. But would such an evaluator give the programmer control about where exactly it would stop optimistic evaluation? Olaf -- OLAF CHITIL, Computing Laboratory, University of Kent, Canterbury, Kent CT2 7NF, UK. URL: http://www.cs.kent.ac.uk/people/staff/oc/ Tel: +44 (0)1227 824320; Fax: +44 (0)1227 762811
participants (6)
-
Adrian Hey
-
Carsten Schultz
-
Duncan Coutts
-
Malcolm Wallace
-
Olaf Chitil
-
Tomasz Zielonka