More speed please!

Duncan Coutts duncan.coutts at
Sat Mar 17 03:23:11 EDT 2007

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.


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.


More information about the Glasgow-haskell-users mailing list