严格声明的意义何在?

Posted

技术标签:

【中文标题】严格声明的意义何在?【英文标题】:What is the point of the strictness declaration? 【发布时间】:2011-06-03 19:36:21 【问题描述】:

我正在启动 Haskell,并正在研究一些用“!”定义数据类型的库。来自字节串库的示例:

data ByteString = PS -# UNPACK #- !(ForeignPtr Word8) -- payload
                     -# UNPACK #- !Int                -- offset
                     -# UNPACK #- !Int                -- length

现在我看到 this question 来解释这意味着什么,我想这很容易理解。但我现在的问题是:使用它有什么意义?既然表达式会在需要时被评估,为什么要强制提前评估?

在这个问题的第二个答案中,C.V.汉森说:“[...] 有时懒惰的开销可能太多或浪费”。是不是说它是用来节省内存的(保存值比保存表达式便宜)?

一个解释和一个例子会很棒!

谢谢!

[EDIT] 我想我应该选择没有 -# UNPACK #- 的示例。所以让我自己做一个。这会有意义吗?是的,为什么以及在什么情况下?

data MyType = Const1 !Int
            | Const2 !Double
            | Const3 !SomeOtherDataTypeMaybeMoreComplex

【问题讨论】:

惰性会对代码产生很多影响,主要是惰性程序通常在线性空间中运行,而严格程序需要恒定空间。但在您的示例中,真正的原因可能与有问题的数据被不知道如何强制延迟评估的外部函数操作有关。 不。 ForeignPtr 可以传递给外部函数,当然,但不能传递给结构本身——即使有严格/解包注释,也没有为本地 haskell 结构定义 ABI 【参考方案1】:

这里的目标不是严格,而是将这些元素打包到数据结构中。如果没有严格性,这三个构造函数参数中的任何一个都可以指向堆分配的值结构或堆分配的延迟评估thunk。严格来说,它只能指向堆分配的值结构。通过严格性和压缩结构,可以将这些值内联。

由于这三个值中的每一个都是指针大小的实体,并且无论如何都被严格访问,因此在使用此结构时,强制使用严格和压缩结构可以节省指针间接。

在更一般的情况下,严格性注释可以帮助减少空间泄漏。考虑这样一个案例:

data Foo = Foo Int

makeFoo :: ReallyBigDataStructure -> Foo
makeFoo x = Foo (computeSomething x)

如果没有严格性注释,如果您只调用makeFoo,它将构建一个指向ReallyBigDataStructure 的thunk 的Foo,并将其保留在内存中,直到某些东西迫使thunk 评估。如果我们有

data Foo = Foo !Int

这会强制 computeSomething 评估立即进行(好吧,只要有东西强制 makeFoo 本身),这样可以避免留下对 ReallyBigDataStructure 的引用。

请注意,这是与字节串代码不同的用例;字节串代码非常频繁地强制其参数,因此不太可能导致空间泄漏。最好将字节串代码解释为纯优化以避免指针取消引用。

【讨论】:

也许我应该选择一个没有打包/拆包的示例(我不明白/还没有看过)。无论如何,“指针大小”的实体是什么意思?我想我对指针有点困惑,因为据我了解,Haskell 并没有真正的指针。这是某种低级编译器相关的东西(不是haskell本身的一部分)吗? 是的,这是对结构的实际内存表示的低级优化。 好吧,这是有道理的。但是我已经编辑了我的答案并添加了另一个示例(^^)。在这种情况下,相同的答案是否有效? 完美!正是我需要的解释。虽然我必须说,我会认为编译器会优化它。我的意思是,就我目前的理解而言,懒惰的意义在于性能......但无论如何感谢您的精彩回答! 还有很多情况下额外的严格是安全的,编译器可以证明这一点,并且确实会优化你的代码。 GHC 非常聪明,即使不是无所不知(至少在当前版本中)。

以上是关于严格声明的意义何在?的主要内容,如果未能解决你的问题,请参考以下文章

var 关键字的意义何在? [复制]

Doctype作用?严格模式与混杂模式如何区分?它们有何意义

html的doctype作用?严格模式与混杂模式如何区分?它们有何意义

Doctype 严格模式与混杂模式-如何触发这两种模式,区分它们有何意义?

Doctype作用?严格模式与混杂模式如何区分?它们有何差异?

Doctype作用?严格模式与混杂模式如何区分?它们有何意义?