GHC中构造函数头(constructor header)的作用与必要性问询
GHC构造函数头的作用与相关疑问
GHC的堆内存中,每个对象都带有头部信息。假设我定义了如下数据类型:
data X = X1 Int# | X2 Int# Int#
我对已求值实例的内存占用理解如下:X1实例占用3个词,X2实例占用4个词——分别是一个指向X1或X2的带标签指针、一个构造函数头,再加上1个或2个词的字段数据。
但我始终疑惑:构造函数头的具体作用是什么?我清楚Haskell在运行时会擦除所有类型信息,且默认不支持运行时反射(除非使用Typeable这类扩展):
- 对于
f :: a -> a这类多态函数,它除了复制a之外无法执行任何其他操作,不需要检查对象本身,直接复制指针即可; - 对于
g :: Num a => a -> a这类带类型类约束的函数,编译时会生成对应的类型类字典(比如调用g (42 :: Int)时的Num Int字典),该字典已经包含了Int的内存布局信息,运行时完全不需要通过头信息来获取相关内容。
那么构造函数头到底在哪些必需的场景下会被运行时代码实际检查?
补充疑问
- 若类型仅包含一个构造函数,是不是完全不需要构造函数头?
- 若类型的构造函数数量不超过7个(32位系统下不超过3个),指针标记(pointer tagging)是否可以替代构造函数头?毕竟未求值的thunk不需要知道构造函数,求值后也可以通过带标记指针指向对象,似乎压根用不着头信息。
内容的提问来源于stack exchange,提问作者Clinton
相关产品推荐
相关产品推荐

