Mmmm, let's give a slightly different example:  

foo :: Foo -> Int
foo (Foo a) = a + 1

bar :: Int -> Int
bar = foo . Foo

and I'd expect bar to be replaced with (foo `cast` (Int -> Int)) and inlined, eliminating an allocation.  In general, we'd get the equivalent of the no-allocation versions of GeneralizedNewtypeDeriving instances, so long as we could write them out for ourselves.

Louis Wasserman
wasserman.louis@gmail.com
http://profiles.google.com/wasserman.louis


On Tue, Jul 13, 2010 at 9:09 AM, Simon Peyton-Jones <simonpj@microsoft.com> wrote:

It compiles to

 

lift f d = f (d `cast` blah)

 

which seems fine to me.  Are you unhappy with that?

 

Simon

 

From: glasgow-haskell-users-bounces@haskell.org [mailto:glasgow-haskell-users-bounces@haskell.org] On Behalf Of Louis Wasserman
Sent: 09 July 2010 03:30
To: glasgow-haskell-users@haskell.org
Subject: Casting + eta reduction

 

Consider

 

newtype Foo = Foo Int

 

lift :: (Int -> a) -> Foo -> a

lift f (Foo x) = f x

 

Now, I'd expect this to compile with -O2 down to something like

 

lift f = f `cast` (Foo -> a)

 

but it doesn't.

 

It seems that GeneralizedNewtypeDeriving assumes that these two things *are* equivalent, and it just directly casts the class dictionary.  The implication would be that that GeneralizedNewtypeDeriving gives more efficient instances than you could *possibly* get if you wrote them by hand, which is very sad.