unboxed类型和严格性之间的关系是什么?

时间:2010-06-28 10:18:48

标签: haskell lazy-evaluation evaluation strictness

未装箱的类型,如Int#和严格的功能,如f (!x) = ...,是不同的,但我看到概念上的相似性 - 他们在某种程度上不允许暴力/懒惰。如果Haskell是像Ocaml这样的严格语言,那么每个函数都是严格的,并且每个类型都是未装箱的。未装箱的类型与强制执行之间的关系是什么?

3 个答案:

答案 0 :(得分:35)

未装箱与装箱数据

为了支持parametric polymorphismlaziness,默认情况下,Haskell数据类型统一表示为closurethe heap的指针,其结构如下:

alt text

这些是“盒装”值。 unboxed 对象由值本身直接表示,没有任何间接或闭包。 <{1}}已装箱,但Int已取消装箱。

延迟值需要一个盒装表示。严格的值不会:它们既可以表示为堆上的完全计算闭包,也可以表示为原始的未装箱结构。请注意,pointer tagging是我们可以在盒装对象上使用的优化,用于在指向闭包的指针中编码构造函数。

与严格的关系

通常,未装箱的值是由功能语言编译器以临时方式生成的。然而,在Haskell中,unboxed values是特殊的。它们:

  1. 他们有不同的种类,Int#;
  2. 只能在特殊场所使用;和
  3. 它们未被提升,因此不表示为指向堆值的指针。
  4. 因为他们没有举起,所以他们必须严格。懒惰的表现是不可能的。

    因此,特定的未装箱类型,如#Int#,在机器上实际上只表示为double或int(用C表示法)。

    严格性分析

    另外,GHC执行strictness analysis常规Haskell类型。如果发现值的使用是严格的 - 即它永远不会'未定义' - 优化器可能会将常规类型的所有用法(例如Double#)替换为未装箱的(Int),因为它知道Int#的使用始终是严格的,因此用更有效(并且始终严格)的Int类型替换是安全的。

    我们当然可以有没有未装箱类型的严格类型,例如,元素严格的多态列表:

    Int#

    在其元素中是严格的,但不会将它们表示为未装箱的值。

    这也指出了你对严格语言like OCaml的错误。他们仍然需要支持多态,因此要么提供统一的表示,要么将数据类型和函数专门化为每种类型。 GHC默认使用统一表示,OCaml也是如此,尽管GHC现在也可以specialize types and functions(就像C ++模板一样)。

答案 1 :(得分:16)

未装箱的类型必须严格,但并非所有严格的值都必须取消装箱。

data Foo a = Foo !a !a

有两个严格的字段

data Bar a = Bar {-# UNPACK #-} !Int !a

有两个严格的字段,但第一个字段是未装箱的。

最终,未装箱的类型(必然)严格的原因是没有地方存储thunk,因为它们只是平坦,愚蠢的数据。

答案 2 :(得分:8)

任何类型的参数都可以“严格”,但唯一具有相应盒装类型的未装箱类型是Char#Int#Word#Double#和{ {1}}。

如果您了解像C这样的低级语言,则更容易解释。未装箱的类型就像Float#int等,盒装类型就像doubleint*等。当你有double*时,你已经知道它在位模式中表示的整个值,因此,它不是懒惰的。它也必须严格,因为int的所有值都是有效的而不是⊥。

但是,给定int,您可以选择稍后取消引用指针以获取实际值(因此是惰性的),并且可能有无效指针(它包含⊥,即非严格)。 / p>