2010-06-28 230 views
23

无盒类型,如Int#和严格函数,如f (!x) = ...,有些不同,但我看到概念上的相似性 - 它们以某种方式不允许thunk/laziness。如果Haskell是像Ocaml这样严格的语言,那么每个函数都将是严格的,每种类型都会被拆箱。拆箱类型和严格执行之间的关系是什么?拆箱类型和严格性之间的关系是什么?

+1

我对拆箱类型没有太多经验,所以即使是基本的评论也是受欢迎的。 – sdcvvc 2010-06-28 10:22:59

+3

由于多态性,并非所有类型都将被拆箱。 OCaml和Haskell中的多态函数使用值的统一表示法作为闭包。 Haskell允许专门化,生成使用非盒装参数的自定义函数(OCaml可能也会这样做)。 – 2010-06-28 16:36:14

回答

32

无盒装VS盒装数据

为了支持parametric polymorphismlaziness,默认情况下Haskell的数据类型被统一表示为一个指向closurethe heap,具有这样的结构:

alt text

这些是“盒装”值。一个拆箱对象由值本身直接表示,没有任何间接或闭包。 Int已装箱,但Int#已取消装箱。

懒惰值需要一个盒装表示。严格的值不会:它们可以表示为堆中完全评估的闭包,或者表示为原始的拆箱结构。请注意,pointer tagging是我们可以在盒装对象上使用的优化,用于将指针中的构造函数编码为闭包。

的关系,以严格

通常,在由功能语言编译器的特设的方式生成装箱值。但在Haskell中,unboxed values是特殊的。他们:

  1. 他们有不同的种类,#;
  2. 只能在特殊的地方使用;和
  3. 它们未被提升,所以不被表示为指向堆值的指针。

因为它们未被提升,所以它们必然是严格的。懒惰的表示是不可能的。

因此,特别的拆箱类型,例如Int#,Double#,在机器上确实表示为double或int(以C表示法)。

严谨分析

另外,GHC不正规的Haskell类型strictness analysis。如果一个值的使用被认为是严格的 - 也就是说它永远不会被定义为'未定义的 - 优化器可能会取代常规类型的所有用途(例如Int)与一个非盒装的(Int#),因为它知道使用Int是总是严格的,因此用更高效(并且总是严格)的类型Int#替换是安全的。

我们当然可以有严格的类型,而拆箱类型,例如,一个元素严格多态性名单:

data List a = Empty | Cons !a (List a) 

是其元素严格,但并不代表他们作为拆箱值。

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

+0

那么有没有使用严格的盒装类型,就像你的'List'例子?它是否与懒惰的对象具有相同的表示形式? – haskelline 2012-07-03 08:15:03

+0

它具有相同的表示形式,但语义不同。这样的结构通常是有用的。 – 2012-07-03 12:29:22

+1

但我认为,例如'data Pair = P Int Int'将包含比'data Pair = P!Int!Int'更多的间接字符。在前者中,每个参数是指向一个指针(一个thunk)的指针,而在后者中它是一个指向值的指针? – haskelline 2012-07-03 13:25:57

17

拆箱类型必然是严格的,但并非所有严格的值都必须拆箱。

data Foo a = Foo !a !a 

有两个严格的领域

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

有两个严格的领域,但第一个是拆箱。

最终,unboxed类型(必然)严格的原因是没有地方存储thunk,因为它们只是扁平的,在那一点上是哑数据。任何类型的

7

参数可以由“严格”,但具有相应boxed类型的唯一的装箱类型是Char#Int#Word#Double#Float#

如果您知道像C这样的低级语言,则更容易解释。无盒类型类似于int,double等,盒装类型与int*,double*等相同。当您有int时,您已经知道整个值,因为它是以位模式表示的,因此它不是懒。它也必须严格,因为所有int的值都是有效的,而不是⊥。

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

相关问题