18

例如,我有一个在返回fnB :: a -> Bool之前没有意义的操作。在 CI 中可以将这两个操作组合在一个块中:fnA :: BoolFalseif

if( fnA && fnB(a) ){ doSomething; }

并且 C 将保证在返回 falsefnB之前不会执行。fnA

但是 Haskell 是懒惰的,而且通常不能保证首先执行什么操作,除非我们不使用seq,$!或其他东西来使我们的代码严格。一般来说,这就是我们需要快乐的东西。但是使用&&运算符,我希望在返回结果fnB之前不会对其进行评估。fnAHaskell 是否提供这样的保证&&fnB即使fnA返回 False ,Haskell 也会进行评估吗?

4

4 回答 4

34

仅当函数的第一个参数是 时,该函数(&&)的第二个参数才是严格的True。它的第一个论点总是严格的。这种严格/懒惰是保证评估顺序的原因。

所以它的行为与 C 完全一样。不同之处在于在 Haskell 中,(&&)是一个普通函数。在 C 中,这是不可能的。

但是 Haskell 是懒惰的,而且通常不能保证哪个操作会先执行,除非我们不使用 seq、$! 或其他东西来使我们的代码严格。

这是不正确的。真相更深。

严格的速成课程:

我们知道(&&)它的第一个参数是严格的,因为:

⊥ && x = ⊥

在这里,⊥ 类似于undefined无限循环(⊥ 发音为“底部”)。我们也知道(False &&)它的第二个参数是非严格的:

False && ⊥ = False

它不可能评估它的第二个参数,因为它的第二个参数是⊥,它不能被评估。但是,该函数(True &&)的第二个参数是严格的,因为:

True && ⊥ = ⊥

所以,我们说它(&&)的第一个参数总是严格的,只有当第一个参数是 时,它的第二个参数才严格True

评价顺序:

对于(&&),其严格性足以保证执行顺序。情况并非总是如此。例如,(+) :: Int -> Int -> Int在两个参数中总是严格的,因此可以先评估任一参数。但是,您只能通过在IOmonad 中捕获异常或使用unsafe函数来区分。

于 2011-09-30T15:23:57.490 回答
5

正如其他人所指出的,(&&)它的论点之一自然是严格的。根据标准定义,它的第一个参数是严格的。您可以使用flip翻转语义。

作为附加说明:请注意, to 的参数(&&)不能有副作用,因此只有两个原因需要您关心是否x && y是 strict in y

  • 性能:如果y需要很长时间来计算。
  • 语义:如果你期望那y可能是底部。
于 2011-09-30T16:16:54.997 回答
1

Haskell 是懒惰的,而且通常不能保证先执行什么操作

不完全的。Haskell 是的(除了unsafePerformIO和 的实现IO),没有办法观察哪个操作会先执行(除了unsafePerformIO和 的实现IO)。执行顺序与结果无关

&&有一个 9 值真值表,包括一个或两个参数为 的情况undefined,它准确地定义了操作:

a           b           a && b
True        True        True
True        False       False
True        undefined   undefined
False       True        False
False       False       False
False       undefined   False
undefined   True        undefined
undefined   False       undefined
undefined   undefined   undefined

只要实现遵循该表,它就可以按照它想要的任何顺序执行。

(如果您研究该表,您会注意到顺序实现没有办法跟随它,除非它a首先执行,然后biffa为 True。但是 Haskell 实现不需要是顺序的!总是允许实现随时执行b;您唯一的保证是,根据表格,执行结果只有在为 Trueb时才会影响您的程序。)a

(请注意,“懒惰”是编写具有上述真值表的函数的唯一方法;在像 C 或 ML 这样的语言中,任何一个参数中的所有五行undefined都将被强制undefined作为结果,在 Haskell 中(以及在 C 中,因为&&内置于 C 语言中)其中一行可以False作为结果。)

于 2016-08-31T15:30:28.397 回答
-1

我相信它会按您期望的方式工作;如果 LHS 评估为 True,则评估 RHS。但是,假设 RHS 没有副作用,您怎么知道(或关心)?

编辑:我猜 RHS 可能是undefined,然后你会关心...

于 2011-09-30T15:26:33.587 回答