How does GHC's implementation of par work?

This is related to the long thread on a bug in cross-module strictness analysis for the "lazy" function in GHC. Simon posted a response to that bug ( http://hackage.haskell.org/trac/ghc/ticket/3259 ), which shows the Haskell source for GHC's "par" function:
{-# INLINE par #-} par :: a -> b -> b par x y = case (par# x) of { _ -> lazy y }
While I understand that in GHC Core, case always reduces its argument
to WHNF, this isn't true of Haskell in general. What causes par# to
get executed? Does GHC overload case for unboxed return values to
force the evaluation of the scrutinee even if its return value isn't
used?
-- ryan
On Tue, May 26, 2009 at 10:29 AM, Duncan Coutts
On Mon, 2009-05-25 at 09:40 -0400, Mario Blazevic wrote:
$diff main.simpl imported.simpl ... 223c232 < a_s1rs [ALWAYS Just L] :: GHC.Integer.Internals.Integer ---
a_s1sV [ALWAYS Just S] :: GHC.Integer.Internals.Integer ...
Good find!
Does this S vs. L difference have anything to do with strictness and laziness?
Yes.
So, I think we should open a ghc but report with all the details, particularly the example's source, the ghc version and that highlight of that strictness difference.
I have logged the ticket at
Thanks for being so persistent Mario!
Simon has diagnosed the bug. It's really rather subtle.
Duncan
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

2009/5/26 Ryan Ingram
What causes par# to get executed? Does GHC overload case for unboxed return values to force the evaluation of the scrutinee even if its return value isn't used?
As you noted, the type of "par" is a -> Int#. Furthermore, the only possible evaluation semantics for unboxed types in GHC's intermediate language is strict. This means that your case expression has to evaluate the scrutinee eagerly. Indeed, consider the following program (which looks even lazier than your example): let x :: Int# = error "boom!" in 10 This will diverge in either Haskell or Core, because both languages promise that if have an unlifted thing in your environment /it really has been evaluated/. SPJ and I recently wrote a paper [1] proposing an intermediate language for GHC that would allow Core to express thunks of unlifted types, but even so I don't think we would actually want to change the semantics of bindings of unlifted types in Haskell. Cheers, Max [1] http://www.cl.cam.ac.uk/~mb566/papers/tacc-hs09.pdf

I saw your paper on LtU last week. Here's an extra plug: I really enjoyed it.
When can we expect to see Strict Core replacing System Fc? :)
-- ryan
On Tue, May 26, 2009 at 5:32 PM, Max Bolingbroke
2009/5/26 Ryan Ingram
: What causes par# to get executed? Does GHC overload case for unboxed return values to force the evaluation of the scrutinee even if its return value isn't used?
As you noted, the type of "par" is a -> Int#. Furthermore, the only possible evaluation semantics for unboxed types in GHC's intermediate language is strict. This means that your case expression has to evaluate the scrutinee eagerly.
Indeed, consider the following program (which looks even lazier than your example):
let x :: Int# = error "boom!" in 10
This will diverge in either Haskell or Core, because both languages promise that if have an unlifted thing in your environment /it really has been evaluated/. SPJ and I recently wrote a paper [1] proposing an intermediate language for GHC that would allow Core to express thunks of unlifted types, but even so I don't think we would actually want to change the semantics of bindings of unlifted types in Haskell.
Cheers, Max
[1] http://www.cl.cam.ac.uk/~mb566/papers/tacc-hs09.pdf _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (2)
-
Max Bolingbroke
-
Ryan Ingram