【问题标题】:What's the meaning of strict version in haskell?haskell中严格版本的含义是什么?
【发布时间】:2012-12-26 02:18:43
【问题描述】:

关注,据说foldl'foldl的严格版。

但我很难理解,strict 是什么意思??

foldl f z0 xs0 = lgo z0 xs0
         where
            lgo z []     =  z
            lgo z (x:xs) = lgo (f z x) xs


foldl' f z0 xs0 = lgo z0 xs0
    where lgo z []     = z
          lgo z (x:xs) = let z' = f z x in z' `seq` lgo z' xs

【问题讨论】:

  • 对比一下两个版本的foldl的源码,你可能会有所启发。
  • @augustss 也许,你能回答这个问题吗?
  • 如您所见, foldl' 在调用之前计算 lgo 的第一个参数,而 foldl 将(通常)传递一个 thunk,该thunk 将在需要时进行评估。

标签: lazy-evaluation haskell strictness


【解决方案1】:

一个严格的函数是一个函数,它的参数在主体之前被评估。

【讨论】:

  • 不,它不是一个函数,其参数在调用之前被评估。严格的函数,非正式地,是一个评估其参数的函数。
  • 丁多留斯,你是什么意思?
  • 形式上,如果函数在参数为底部时返回底部,则该函数在参数中是严格的。这意味着函数可以是严格的,在形式上,不需要评估参数。这听上去像是扯淡,但在进行严格性分析时很重要。
  • @augustss 这不是这个上下文的意思,不是吗? foldl 在与 foldl' 相同的情况下评估为底部 - 它只是稍后才会这样做,不是吗?
  • @sepp2k: 否。例如:foldl (\x y -> y) (error "empty") [1,undefined,2] 是 2,但与 foldl' 相同的表达式是⊥。
【解决方案2】:

foldl 和(严格的) foldl' 在语义上接近等价。不同之处在于性能,尤其是在您遍历大型列表时。懒惰会产生构建 thunk 的开销,而 foldl' 是获得该结果的更有效方法,因为它不会构建巨大的 thunk。

Haskell Wiki上有一篇非常好的文章详细解释了这一点

严格函数的工作方式类似于 C 或其他语言中的函数,因为它们的参数通常会被急切地求值。

【讨论】:

    【解决方案3】:

    它并不广为人知,但foldl' 实际上在其累加器参数中是非严格的!回忆类型:

    foldl' :: (a -> b -> a) -> a -> [b] -> a
    

    它在参数 2 中的严格性取决于为参数 1 给出的函数的严格性,正如您通过 const 看到的那样:

    Prelude Data.List> foldl' (const (+1)) undefined [1]
    2
    Prelude Data.List> foldl' (const (+1)) undefined [1..4]
    5
    

    您会天真地认为“foldl' 是严格的”意味着“在累加器参数中是严格的”。以上与此相矛盾。

    然而,它更加阴险,因为严格性只针对循环的 cons 情况下函数应用的结果。所以如果你输入基本情况,你仍然会得到底部,而不是归纳情况:

    Prelude Data.List> foldl' (const (+1)) undefined []
    *** Exception: Prelude.undefined
    

    所以严格性in argument 2取决于参数3的

    这就是我的写法:在第二个参数中“完全”严格。

    foldl' f z0 xs0 = go z0 xs0
      where
        go !z []     = z
        go !z (x:xs) = go (f z x) xs
    

    如您所见,第二个参数是真正严格的:

    Prelude Data.List.Stream> foldl' (\a b -> 1) undefined [undefined]
    *** Exception: Prelude.undefined
    

    与Haskell2010版本对比:

    Prelude Data.List.Stream> Data.List.foldl' (\a b -> 1 ) undefined [undefined]
    1
    

    这实际上具有实际影响——当前定义不会一致地拆箱其累加器参数。

    历史记录:这是我们在 2007 年为流融合论文指定列表库的严格语义时发现的,指定严格的方法在 Duncan Coutt 的 PhD thesis 中给出。

    【讨论】:

      猜你喜欢
      • 2016-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-16
      • 1970-01-01
      • 2018-11-27
      • 2017-03-29
      相关资源
      最近更新 更多