#ifdef considered harmful (was: DData)

Jan-Willem Maessen - Sun Labs East Janwillem.Maessen at Sun.COM
Mon Apr 19 15:38:18 EDT 2004

Sven Panne wrote:
> Jan-Willem Maessen - Sun Labs East wrote:
>> [...] The actual problem is function arguments.  GHC can't do
>> worker-wrapper unless a function is strict.  Often we end up with
>> something like this:
>> data Tree a = Branch !Int a (Tree a) (Tree a)
>> lookfor :: Int -> Tree a -> Maybe a
>> lookfor Leaf key = Nothing
>> lookfor (Branch k v l r) key
>>   | key==k    = Just v
>>   | key < k   = lookfor l key
>>   | otherwise = lookfor r key
>> Here we don't use "key" in the first clause, so GHC isn't allowed to
>> unbox.  Most of the uses of Int# that I've seen in library code have
>> been workarounds to this problem. [...]
> If that's the only concern, there is no real problem. One can do:
> a) Help GHC a bit by hand with something like
>       lookfor Leaf key | key == key = Nothing
>    or
>       lookfor Leaf key = key `seq` Nothing
>    Not very nice, but a "traditional" way of improving strictness.

And, of course, we need to remember to do it uniformly everywhere in 
our program.  Figuring out where to put these things isn't always 
easy.  And frankly, I'd love to stamp out the use of equality for 
strictification once and for all.

> b) Use GHC's -O2 flag, enabling specialization over constructors, which
>    is exactly what you're looking for, see the "Game Plan" comment at
>    the beginning of
> http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/ghc/compiler/specialise/SpecConstr.lhs?rev=1.20&content-type=text/x-cvsweb-markup 

I had a fascinating conversation with Simon P-J some years back on 
exactly this subject.  It's a lovely optimization.  But (as you point 
out) I need to do -ddump-simpl (and understand the results) to be sure 
the compiler's done it for me.  Tomorrow, the compiler could (for some 
reason) decide not to do it anymore.  It's all terribly fragile.

Fundamentally, the idea here is to give a library implementor another 
tool to say what they mean.  They can be assured of reasonable-looking 
code that's still tuned to run like the blazes---with the confidence 
of a types backing them up.  They don't have to go crawling through 
their code or the simplifier output a line at a time.   Unboxed types 
were designed with exactly that goal in mind.  But they're not 
portable.  I'm suggesting a lightweight, simple wrapper which would be 
portable.  Perhaps that wrapper should even be named "Int#"!

>    Using "-O2 -ddump-simpl" with your (slightly corrected) example, one
>    can see that the Ints are indeed unboxed during recursion.
> Cheers,
>    S.

More information about the Libraries mailing list