gpt4 book ai didi

haskell - 为什么在 Haskell 中系统地标记记录字段?

转载 作者:行者123 更新时间:2023-12-04 14:54:21 25 4
gpt4 key购买 nike

我已经读过好几次了,在 Haskell 中系统地标记记录的字段是一种很好的做法,例如代替

data Foo = Foo { bar :: Bar, quux :: Quux }


data Foo = Foo { bar :: !Bar, quux :: !Quux}

例如,这里引用了 Haskell Programming from First Principles ,第 1134 页:

A good rule to follow is lazy in the spine, strict in the leaves!



我(想我)明白什么是严格以及两者之间的区别。我不明白的是为什么后者系统地做?

最佳答案

一个常见的经验法则是在以下情况下使数据结构严格:

  • 你期望严格遍历整个东西并保留它,所以懒惰的开销没有意义;或
  • 这些字段是“小”的——小于或等于指针的大小——你希望编译器将它们拆箱以避免不必要的间接。 (-funbox-small-strict-fields 自 GHC 7.7 起默认开启。)

  • 这在实践中往往与“脊椎懒惰,叶子严格”大致相同,因为数据结构通常会从懒惰中受益,但它们的内容通常不会。

    “系统地”执行此操作是帮助避免空间泄漏的一种天真的方法 - 例如,如果您重复修改数据结构(例如累加器)而不同时强制值:
    ghci> data Lazy = Lazy { lazyField :: Int } deriving (Show)

    ghci> data Strict = Strict { strictField :: !Int } deriving (Show)

    ghci> modifyLazy (Lazy field) = Lazy { lazyField = field + 1 }

    ghci> modifyStrict (Strict field) = Strict { strictField = field + 1 }

    ghci> lazy = iterate modifyLazy (Lazy 0) !! 1000000

    ghci> strict = iterate modifyStrict (Strict 0) !! 1000000

    ghci> :set +s

    ghci> lazy
    Lazy {lazyField = 1000000}
    (0.76 secs, 251,792,080 bytes)

    ghci> strict
    Strict {strictField = 1000000}
    (0.52 secs, 178,173,544 bytes)

    懒惰的版本在强制它之前会建立一个 thunk 链;严格版本在每一步都对 Int 字段进行全面评估。 modifyIORef(惰性)和 modifyIORef'(严格)也会发生类似的情况。

    在非严格类型的字段上添加严格注释几乎没有意义,例如, field :: ![Int] 仅确保强制第一个 (:)[] 构造函数;它不会使整个列表变得严格。如果需要,您可能需要一个严格的序列类型,例如 Data.Vector 。并且通常不建议将多态字段设置为严格,例如 data Foo a = Foo … !a … ,因为使用该类型的人可能期望能够依赖那里的惰性——例如,在使用循环的算法中(“打结”)——和不得不将类型包装在像 data Lazy a = Lazy a 这样的额外构造函数中以重新获得惰性是很烦人的。懒惰在等式推理中也表现得更好——尽管在实践中我们经常使用忽略严格性和非全函数的“快速和松散”的等式推理。

    最终,决定某些东西应该是惰性还是严格的唯一方法是考虑您的特定应用程序所需的语义,并在性能分析之后添加明智的严格性(字段上的刘海、 BangPatternsseq、像 modifyIORef' 这样的严格函数)问题或空间泄漏。

    关于haskell - 为什么在 Haskell 中系统地标记记录字段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50502350/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com