Dmi*_*lov 15 haskell logical-operators strictness
例如,我有一个fnB :: a -> Bool在fnA :: Bool返回之前没有意义的操作False.CI中可以将这两个操作组合在一个if块中:
if( fnA && fnB(a) ){ doSomething; }
Run Code Online (Sandbox Code Playgroud)
和C将保证fnB在fnA返回false 之前不会执行.
但Haskell是惰性的,并且,通常也不能保证什么操作将首先执行,直到我们不使用seq,$!或别的东西,使我们的代码严格.一般来说,这就是我们需要快乐的事情.但是使用&&运算符,我希望fnB在fnA返回结果之前不会对其进行求值.Haskell提供这样的保证&&吗?fnB即使fnA返回False,Haskell也会评估吗?
Die*_*Epp 32
(&&)仅当第一个参数为第二个参数时,该函数才是严格的True.它的第一个论点总是严格的.这种严格/懒惰是保证评估顺序的原因.
所以它的行为与C完全相同.不同之处在于Haskell中(&&)是一个普通的函数.在C中,这是不可能的.
但是Haskell是懒惰的,并且通常不能保证首先执行什么操作,直到我们不使用seq,$!或其他东西来使我们的代码严格.
这是不正确的.事实更深刻.
严格的速成课程:
我们知道(&&)它的第一个参数是严格的,因为:
? && x = ?
Run Code Online (Sandbox Code Playgroud)
在这里,⊥是类似的undefined或无限循环(⊥发音为"bottom").我们也知道(False &&)第二个论点是非严格的:
False && ? = False
Run Code Online (Sandbox Code Playgroud)
它不可能评估它的第二个参数,因为它的第二个参数是⊥,它不能被评估.但是,该函数(True &&)在其第二个参数中是严格的,因为:
True && ? = ?
Run Code Online (Sandbox Code Playgroud)
所以,我们说(&&)第一个参数总是严格的,第二个参数只有第一个参数时才严格True.
评估顺序:
因为(&&),它的严格属性足以保证执行顺序.情况并非总是如此.例如,(+) :: Int -> Int -> Int两个参数中始终都是严格的,因此可以首先计算任一参数.但是,您只能通过捕获IOmonad中的异常或使用unsafe函数来区分.
小智 5
正如其他人所指出的那样,(&&)其中一个论点自然是严格的.按照标准定义,它的第一个论点是严格的.您可以使用flip翻转语义.
作为补充说明:请注意,参数(&&)不能产生副作用,因此只有两个原因可以解释为什么要x && y严格遵守y:
y需要很长时间来计算.y可以是最低点.