
Tom Ellis
On Mon, Jul 31, 2017 at 11:44:20PM +0200, Nick Smallbone wrote:
* The type must not be just a type variable (i.e., the constructor must be known at compile time)
Eventually I'd like to see if we can relax this condition but first ...
(Take everything I say here with a pinch of salt: I'm not a GHC developer.) IIUC, relaxing this would be difficult because GHC compiles using type erasure. For example, if I have a type data Whatever a = Whatever !a then values of type Whatever Int and Whatever Float are represented in exactly the same way at runtime. However, if we were to unpack the 'a', then they would internally have to be turned into two different types: data WhateverInt = Whatever Int# data WhateverFloat = Whatever Float# This would in turn mean that a polymorphic function f :: Whatever a -> ... would have to be compiled into two separate versions, one for Whatever Int and one for Whatever Float, which is something that GHC doesn't do.
* The field's type must have only one constructor
Do you know the rationale for this? It seems like there should be no problem unpacking a constructor tag plus payload, even if the payload size varies, as long as the maximum payload size in known.
One thing is that UNPACK right now can be implemented just by a simple program transformation. When you declare a datatype with an unpacked field, such as data T a b = C {-# UNPACK #-} !Int {-# UNPACK #-} !(a, b), then GHC secretly replaces the datatype with the unpacked version, in this case: data T a b = UnpackedC Int# a b Then all uses of the constructor C are rewritten to use UnpackedC instead. The resulting program is still type-correct - in fact, it is still a normal Haskell (well, GHC core) program. This transformation happens quite early on during compilation and AIUI the rest of the compiler doesn't have to know about unpacking at all. If you try to unpack a field that has multiple constructors this way, it's not clear what the unpacked datatype should look like - I suppose it'd need to be some kind of union. So at least it's not immediately obvious how to do this... Nick