I noticed this pattern is very common in Haskell libraries:
data Foo = Foo { field :: {-# UNPACK #-} !Sometype }
e.g. UNPACK
ing a field's type and making it strict.
I understand what's the effect of the pragma and annotation but I don't understand why it is so pervasive: I have been programming in Haskell for 15 years and seldom used strictness annotation, and never UNPACK
pragma.
If this idiom is so useful, why not make it less "ugly"?
The pragma may be a bit ugly, but it avoids a lot more ugliness elsewhere. When performance is critical, programmers often need to choose a particular shape for a data constructor. Suppose I have
data Point = Point Int Int
data Segment = Segment Point Point
That makes good logical sense, but it has a bunch of extra indirection: one Segment
consists of seven heap objects. If I'm working with a lot of segments, that's pretty bad.
I could squash this flat by hand:
data Segment = Segment Int# Int# Int# Int#
but now I've lost the fact that the numbers represent points, and everything I do with a segment will have to involve rather inconvenient and weird unboxed operations.
Fortunately, there's a better way:
-- The small strict Int fields will be unpacked by default
-- with any reasonably recent GHC version.
data Point = Point !Int !Int
data Segment = Segment {-# UNPACK #-} !Point {-# UNPACK #-} !Point
This still gives me one heap object per segment, but I can use Point
s and Int
s and (generally) rely on the compiler unboxing everything nicely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With