繁体   English   中英

haskell 在处理复杂的程序流程时有多懒惰

[英]how lazy is haskell when dealing with complicated program flow

我想知道 Haskell 有多聪明/懒惰。 我能否始终确定 Haskell 只会执行生成某个 output 所需的操作?

不。

Haskell 为其核心类 lambda 演算指定了指称语义,您可以依赖该语义。 此外,还有一个元理论证明,一个特定的归约顺序——俗称“惰性求值”——实现了这种语义; 很多人将其用作 Haskell 程序行为方式的心理 model。

Haskell 程序可能最终评估超出必要的两种方式:

  • Haskell 实现可以选择评估更多。 GHC 在大部分地方都使用惰性求值,但我相信在某些情况下它会使用其他求值顺序来提高效率。 您还可以查看Eager Haskell项目,它正在尝试使用另一种实现策略; 或者,原则上,实现将有权选择推测性地将某些计算分叉到另一个线程(然后在不需要时丢弃结果)。

  • 指定的指称语义可能需要比“必要”更多的评估。 例如,偶尔会绊倒初学者的一个:

     primes:: [Int] primes = 2: filter prime [3,5..] prime:: Int -> Bool prime x = and [x `mod` p /= 0 | p <- primes, p < x]

    在检查3是否应该在列表primes中时,实际上没有必要检查超过2primes的任何元素,因为该序列是严格单调递增的。 但是 Haskell 不够聪明(不尝试)来注意到这一点; 它将 go 直接尝试检查primes的 rest 并最终进入无限循环,而不是给出素数列表。

    一个更小的例子:你可以认为x && False总是False ,但x通常会被评估,因为语义表明如果x是,这应该是一个无限循环。 (对比False && x ,这通常不会导致评估x 。)

也就是说,当您说“复杂结构”时,想到的一件事是:即使使用我定义的自定义数据类型, Haskell 也会做懒惰的事情吗? 也就是说,像 hash 映射和平衡树和 kd 树等复杂结构会被延迟处理吗? 答案是肯定的; 除了IO之外, Prelude中的任何类型都没有什么特别之处。 列表、布尔值、 Maybe等是惰性的,不是因为编译器知道关于它们的特殊信息,而是因为 Haskell 指定的缩减规则及其作为类型的声明。

当然,有一些方法可以选择退出懒惰。 您将在 Hackage 上看到的一些结构以各种方式做到这一点; 但别担心,通常这会在他们的文档中声明。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM