3
votes

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#
2
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 with Int (as far as the type system is concerned anyway).Cubic
Note you are missing an ! before the Int for the UNPACK variant.Alec
If I am reading the docs right, there is no difference between these.Alec
@Cubic: fair enough. But in this case the type Int# is defined. Is there still any difference between {-# UNPACK #-} !Int and Int#? And is the general difference merely that {-# UNPACK #-} can be used with any type, whereas Type# can only be used with the limited list of types including Int#?George
In general, however, UNPACK is more powerful as it can flatten more complex data structures automatically.Alec

2 Answers

3
votes

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.

1
votes

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).