sdc*_*vvc 29 evaluation haskell lazy-evaluation strictness
未装箱的类型,比如Int#
,和严格的功能,f (!x) = ...
是不同的,但我看到概念上的相似性 - 他们在某种程度上不允许暴力/懒惰.如果Haskell是像Ocaml这样的严格语言,那么每个函数都是严格的,并且每个类型都是未装箱的.unboxed类型与强制执行之间的关系是什么?
Don*_*art 35
Unboxed vs Boxed Data
To support parametric polymorphism and laziness, by default Haskell data types are represented uniformly as a pointer to a closure on the heap, with a structure like this:
These are "boxed" values. An unboxed object is represented by the value itself directly, without any indirection or closure. Int
is boxed, but Int#
is unboxed.
Lazy values require a boxed representation. Strict values do not: they can represented either as fully evaluated closures on the heap, or as primitive unboxed structures. Note that pointer tagging is an optimization that we can use on boxed objects, to encode the constructor in the pointer to the closure.
与严格的关系
通常,未装箱的值由功能语言编译器以临时方式生成.但是,在Haskell中,未装箱的值是特殊的.他们:
#
;因为他们没有举起,所以他们必须严格.懒惰的表现是不可能的.
因此,特定的未装箱类型,例如Int#
,Double#
在机器上实际上表示为double或int(在C表示法中).
严格性分析
另外,GHC 对常规Haskell类型进行严格分析.如果发现值的使用是严格的 - 即它永远不会是'未定义' - 优化器可能会将常规类型(例如Int
)的所有用法替换为未装箱的(Int#
),因为它知道使用Int
始终是严格的,因此用更有效(并且始终严格)的类型替换Int#
是安全的.
我们当然可以有没有未装箱类型的严格类型,例如,元素严格的多态列表:
data List a = Empty | Cons !a (List a)
Run Code Online (Sandbox Code Playgroud)
它的元素是严格的,但不表示它们是未装箱的值.
这也指出了你对严格语言的错误,比如OCaml.他们仍然需要支持多态,因此要么提供统一的表示,要么将数据类型和函数专门化为每种类型.GHC默认使用统一表示,OCaml也是如此,尽管GHC现在也可以专门化类型和函数(如C++模板).
Edw*_*ETT 16
未装箱的类型必须严格,但并非所有严格的值都必须是未装箱的.
data Foo a = Foo !a !a
Run Code Online (Sandbox Code Playgroud)
有两个严格的领域
data Bar a = Bar {-# UNPACK #-} !Int !a
Run Code Online (Sandbox Code Playgroud)
有两个严格的字段,但第一个是未装箱的.
最终,未装箱类型(必然)严格的原因是没有地方存储thunk,因为它们只是平坦,愚蠢的数据.
任何类型的参数可以进行"严格",但有相应的boxed类型的唯一拆箱类型Char#
,Int#
,Word#
,Double#
和Float#
.
如果您了解像C这样的低级语言,则更容易解释.未装箱的类型就像int
,double
等等,盒装的类型就像int*
,double*
等等.当你有一个int
,你已经知道它在位模式中表示的整个值,因此,它不是懒惰的.它也必须严格,因为所有的值int
都是有效的而不是⊥.
但是,给定一个int*
你可以选择稍后取消引用指针以获得实际值(因此是懒惰的),并且可能有无效指针(它包含⊥,即非严格).