More speed please!

Simon Peyton-Jones simonpj at microsoft.com
Tue Mar 20 11:57:01 EDT 2007


I'm not sure how to make progress with this thread (see below).  On the one hand there is an interesting idea here.  On the other, I don't want to put more ad-hoc-ery into GHC.

What this cries out for is a notion of strict function *in the types*.  So if
        f :: !Int -> Int
then you know that f is strict, and you can use call-by-value.  GHC has no such notion at the moment. The bangs in constructors are very specific to constructors, and handled in an ad-hoc way.

Duncan wants to make them more first class, which is good.  But that would mean making !T into a Core type, not just a source-language annotation on data constructors.  Doing this in a systematic way is attractive, but slippery. Ben Rudiak-Gould has spent quite a bit of time thinking about it.  There are many questions; e.g: can ! appear to the right of an arrow?  inside tuples (!a,!b)?  inside lists [!a]?  Can a polymorphic function be called at a bang-type? etc

Anyway, I'm inclined to make haste slowly on this one.  If someone feels like working out the details, the way lies open. Alternatively, the ad-hoc solution might be so important that it's worth implementing despite its ad-hocery.

Simon

| -----Original Message-----
| From: Duncan Coutts [mailto:duncan.coutts at worc.ox.ac.uk]
| Sent: 17 March 2007 07:23
| To: Simon Peyton-Jones
| Cc: glasgow-haskell-users at haskell.org
| Subject: RE: More speed please!
|
| On Fri, 2007-03-16 at 17:49 +0000, Simon Peyton-Jones wrote:
| > | newtype Put a = Put {
| > |         runPut :: (a -> {-# UNPACK #-} !Buffer -> [B.ByteString])
| > |                      -> {-# UNPACK #-} !Buffer -> [B.ByteString]
| > |     }
|
| > Now you are proposing that
| >
| >         data Bar a = MkBar (!a -> a)
| >
| > means this:
| >
| >         MkBar f = :MkBar (\x. x `seq` f x)
| >
| > That is, even if the argument to MkBar is a lazy function, when you take a MkBar apart you'll find a
| strict function.
|
| Right.
|
| And then after this semantic change we can do tricks like changing the
| calling convention of this function so that it takes that strict
| argument as its unpacked components.
|
| > I suppose you can combine the two notations:
| >
| >         data Baz a = MkBaz !(!a -> a)
| > means
| >         MkBaz f = f `seq` :MkBaz (\x. x `seq` f x)
|
| I suppose so.
|
| > Interesting.  Is that what you meant?  An undesirable consequence would be that
| >         case (MkBar bot) of MkBar f -> f `seq` 0
| > would return 0, because the MkBar constructor puts a lambda inside.
| > This seems bad.  Maybe you can only put a ! inside the function type
| > if you have a bang at the top (like MkBaz).
|
| Hmm, yes I see.
|
| Well that seems like a reasonable restriction. In my original example I
| was using newtype rather than data (which of course is like data with !
| on the only component).
|
| Afterall, in practise I think the main use of this semantic change will
| be to take advantage of faster calling conventions and so we'd be
| perfectly happy with being strict in function itself.
|
| Duncan



More information about the Glasgow-haskell-users mailing list