Haskell在什么程度上懒惰?

我需要一些关于Haskell的懒惰的澄清。

如果我有这个功能:

myFunction arg
  | arg == 1 = a
  | arg == 2 = a*b
  | arg == 3 = b+c
  | otherwise = (a+b)*c
     where
            a = ...
            b = ...
            c = ...
            d = ...

当我调用myFunction 1 ,Haskell将只评估a = ...函数,既不b也不c ,也不d

但是,如果我写

myFunction arg
  | arg == 1 = a
  | arg == 2 = a*b
  | arg == 3 = b+c
  | otherwise = (a+b)*c
     where
            (a,b,c,d) = anotherFunction arg

Haskell的行为是什么?

  • 它会评估只有一个和'传播'到anotherFunction
  • 或者,它会评估整个元组(a,b,c,d)作为anotherFunction结果吗?

  • 在这两种情况下,除非需要价值,否则它不会评估任何东西。 苛刻的值的一种方法是在调用该ghci中函数(它打印在值ghci ,因此,要求它)。 假设你正在执行该函数,那么在第二种情况下,它将评估元组为弱头标准形式(WHNF),然后评估(a,b,c,d)的第一个元素,因为只需要该值。 其他元素bcd将采用thunk形式。 事实上,你可以验证你自己:

    myFunction arg
      | arg == 1 = a
      | arg == 2 = a*b
      | arg == 3 = b+c
      | otherwise = (a+b)*c
      where
        (a,b,c,d) = anotherFunction arg
    
    anotherFunction x = (x, undefined, undefined, undefined)
    

    在ghci中演示:

    λ> myFunction 1
    1
    

    那么它只对a兴趣,所以这意味着有一个隐含的函数

    thea :: (a,b,c,d) -> a
    thea (a,_,_,_) = a
    

    换句话说,Haskell对元组的其他元素不感兴趣 。 然而,有时元组的元素共享某种结构。 说另一个功能被定义为:

    anotherFunction :: Int -> (Int,Int,Int,Int)
    anotherFunction x = (z,t,f,g)
        where f = x*x
              g = f+x
              z = g-2
              t = 3
    

    在这种情况下 - 为了评估第一个元素 - 第三个和第四个元素也将被评估。 但是由于你对他们没有做任何事情,Haskell对他们的结果没有特别的兴趣。


    正如其他人已经指出的,只有a将被评估。

    不过请记住,为了利用懒惰, anotherFunction在评估其组件之前返回一个元组是至关重要的。 例如,考虑

    anotherFunction n = if p > 1000 then (n, p) else (n, 0)
      where p = product [1..n]
    

    即使主叫方只要求第一对分量(即n ),以上将始终评估product [1..n] 。 这是因为if需要在对可以返回之前进行评估,并且强制p 。 相比之下,

    anotherFunction n = (n, if p > 1000 then p else 0)
      where p = product [1..n]
    

    将立即退还这一对。 如果只评估其第一个组件,那么根本不会计算p

    链接地址: http://www.djcxy.com/p/42963.html

    上一篇: To what extent is Haskell lazy?

    下一篇: Why is Haskell missing "obvious" Typeclasses