In GHC, what is the difference between the {-# UNPACK #-}
pragma and the #
type suffix operator?
For example, what is the difference between:
data T = T {-# UNPACK #-} Int
and
data T = T Int#
As you know, from here:
The
UNPACK
indicates to the compiler that it should unpack the contents of a constructor field into the constructor itself, removing a level of indirection
Int#
is the name for GHC's unboxed Int type. Int
is simply a wrapper around this type.
Prelude> import GHC.Int
Prelude GHC.Int> :info Int
data Int = I# GHC.Prim.Int# -- Defined in ‘GHC.Types’
The hash is simply a naming convention for unboxed types which have no heap representation. You'll need to enable the extension -XMagicHash
to refer to these names though.
Maybe it's too obvious to say but the main difference is that in the first case the constructor will have type
T :: Int -> T
and in the second case
T :: Int# -> T
In terms of the runtime representation, there will be no difference (except that I think UNPACK
is ignored if optimizations are disabled). So in the case of T {-# UNPACK #-} !Int
, for example, pattern matching case t of T n -> ...
has to create a new I#
box for n
(which hopefully will cancel with another case
nearby).
Int#
isn't "Int
with some unary operator#
at the end".Int#
is the name of a type, and doesn't really have anything to do withInt
(as far as the type system is concerned anyway). – Cubic!
before theInt
for theUNPACK
variant. – AlecInt#
is defined. Is there still any difference between{-# UNPACK #-} !Int
andInt#
? And is the general difference merely that{-# UNPACK #-}
can be used with any type, whereasType#
can only be used with the limited list of types includingInt#
? – GeorgeUNPACK
is more powerful as it can flatten more complex data structures automatically. – Alec