未包装类型和严格性之间有什么关系?
-
01-10-2019 - |
题
未包装类型,例如 Int#
, 和严格的功能, f (!x) = ...
, ,有所不同,但我看到概念上的相似之处 - 它们在某种程度上不允许thunks/懒惰。如果Haskell是像OCAML这样的严格语言,则每个功能都将是严格的,并且每种类型都没有盒装。未包装类型与强制执行严格之间有什么关系?
解决方案
未盒子与盒装数据
支持 参数多态性 和 懒惰, ,默认情况下,Haskell数据类型统一表示为指向 关闭 在 堆, ,具有这样的结构:
(来源: haskell.org)
这些是“盒装”值。一个 拆箱 对象由值本身直接表示,而无需任何间接或闭合。 Int
被装箱,但是 Int#
被拆箱。
懒值 要求 盒装表示。严格的值不会:它们可以表示为堆上的完全评估的封闭,也可以表示为原始的未盒子结构。注意 指针标记 是我们可以在盒装对象上使用的优化,以在闭合指针中编码构造函数。
与严格关系的关系
通常,功能语言编译器以临时方式生成未盒的值。但是,在哈斯克尔 未框的值 很特别。他们:
- 他们有另一种,
#
; - 只能在特殊的地方使用;和
- 它们是未装修的,因此并未表示为指向堆值的指针。
因为他们是无法置换的,所以他们一定是严格的。 不可能表示懒惰。
因此,特定的未箱类型,例如 Int#
, Double#
, ,实际上是在机器上(以c符号)为double或int表示的。
严格分析
分别是GHC确实 严格分析 常规Haskell类型。如果发现值的使用很严格 - 即永远不会“未定义” - 优化器可能会替换常规类型的所有用途(例如 Int
)带有未包装的一个(Int#
),因为它知道使用 Int
总是严格的,因此用更有效(且始终严格)的类型代替 Int#
是安全的。
当然,我们可以拥有严格的类型,而没有未盒的类型,例如,元素 - 图片多态性列表:
data List a = Empty | Cons !a (List a)
在其元素上是严格的,但并不表示它们为未框的值。
这也指出了您对严格语言的错误, 像Ocaml. 。他们仍然需要支持多态性,因此他们要么提供统一的表示,要么对每种类型的数据类型和功能进行专业化。 GHC默认情况下使用统一表示,OCAML也是如此,尽管GHC也可以 专业类型和功能 现在(例如C ++模板)。
其他提示
未包装的类型必然是严格的,但并非所有严格的值都必须取消框。
data Foo a = Foo !a !a
有两个严格的领域
data Bar a = Bar {-# UNPACK #-} !Int !a
有两个严格的字段,但第一个字段是未包装的。
最终,未盒装类型的原因(一定是严格)是没有地方存储thunk,因为它们只是平坦的,愚蠢的数据。
任何类型的参数都可以“严格”,但是唯一具有相应盒装类型的未框类型是 Char#
, Int#
, Word#
, Double#
和 Float#
.
如果您知道像C这样的低级语言,则更容易解释。未包装类型就像 int
, double
, 等等,盒装类型就像 int*
, double*
, 等等。当你有一个 int
, ,您已经知道以位模式表示的整体值,因此,它并不懒惰。这也必须严格,因为 int
是有效的,不是⊥。
但是,给定一个 int*
您可以选择以后再解释指针以获取实际值(因此懒惰),并且有可能具有无效的指针(其中包含⊥,即非图案)。