我注意到这种模式在Haskell库中非常普遍:
data Foo = Foo { field :: {-# UNPACK #-} !Sometype }
例如UNPACK
字段的类型并使其严格。
我理解编译指示和注释的效果,但我不明白为什么它如此普遍:我已经在Haskell编程了15年,很少使用严格性注释,也从未UNPACK
编译指示。
如果这个成语这么有用,为什么不让它不那么"丑"呢?
编译指示可能有点丑陋,但它避免了其他地方的更多丑陋。当性能至关重要时,程序员通常需要为数据构造函数选择特定的形状。假设我有
data Point = Point Int Int
data Segment = Segment Point Point
这在逻辑上很有道理,但它有一堆额外的间接性:一个Segment
由七个堆对象组成。如果我与很多细分市场合作,那就太糟糕了。
我可以用手压扁这个扁平:
data Segment = Segment Int# Int# Int# Int#
但是现在我已经忘记了数字代表点的事实,我对一个段所做的一切都必须涉及相当不方便和奇怪的未装箱操作。
幸运的是,有一个更好的方法:
-- 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
这仍然为每个段提供了一个堆对象,但我可以使用Point
s 和Int
s,并且(通常(依赖于编译器很好地拆箱。