
On Tue, Jun 5, 2012 at 12:06 AM, Simon Peyton-Jones
I'm sorry I'm still struggling. In your example below you bind 'a' twice, once with the "data UnpackedList a" and once with the "forall a". Did you intend an existential?
I didn't intend the existential. I haven't made any real progress on my unpacking problem since we last talked so lets let it rest for now. I'll try to find some time to write down a wiki page so we at least know where we got stuck last time. Perhaps someone reading it will have an aha moment that will let us move forward.
Also I don't know what you mean by "generate appropriate type definitions at call sites".
If I write: module A data UnpackedList a = Unbox a => Cons {-# UNPACK #-} !a (UnpackedList a) | Nil { -# INLINABLE_DATA UnpackedList #-} -- Like INLINABLE, but for data types module B f :: UnpackedList Int -> ... I'd like GHC to generate data UnpackedListInt = ConsInt {-# UNPACK #-} !Int UnpackedListInt | NilInt and a specialized version of f, using that type, in B. It's a bit like the call-site specialization afforded by the INLINABLE pragma, but applied also to data type definitions. You might protest and say that I could just just use type families, but they don't work well if my type has more than one type parameter (e.g. Map), as I need to write O(n^2) instances: instance Map Int Int where type Map = MapIntInt ...{-# UNPACK #-} !Int {-# UNPACK #-} !Int... instance Map Int Char where type Map = MapIntChar ... instance Map Int (Int, Int) where type Map = MapIntIntInt ... That's 50,625 instances to just cover the basic types (e.g. Int, Word, etc) and pairs. The reason you'd want call-site generation of data types (ala C++ templates) is that a real program would only use no more than 100 (for a big program) of the potentially infinite number of combinations.
Anyway thanks for distinguishing the two threads. If you can clarify the generalised newtype deriving problem too that would be great.
I'll leave it to others. I'm not quite sure what the issue is. -- Johan