gpt4 book ai didi

haskell - `let`和 `where`表达式的结果会存储在haskell中吗?

转载 作者:行者123 更新时间:2023-12-03 04:28:39 28 4
gpt4 key购买 nike

我对 Haskell 相当陌生,阅读 this 后和 some performance tips on strictness我仍然想知道这如何适用于 letwhere表达式。如果我有这样的代码:

f :: Int -> Int -> Int
f a b
|a==b = <simple computation>
|otherwise = e1 + 2 * e1 - e1^2
where e1 = <lengthy computation>

多久会<lengthy computation>被评估?我假设考虑到 Haskell 在 e1 中的惰性求值如果 a==b 则根本不会被评估。但如果不是,就是e1替换为 otherwise表达式,然后在每次遇到它时求值,还是在第一次遇到它时求值,然后存储并在所有后续事件中重用?另外:

  • 有没有办法“手动”控制这个过程?
  • 这是否取决于我在 ghci 中运行代码或使用 GHC 编译代码的天气,在 GHC 编译中它是否取决于像 -o 这样的标志?

这与 this question 非常相似但我找不到 Haskell 的答案。

非常感谢您的解释。

最佳答案

通常,代码在 where 中或let一 block constant applicative form 仅被评估一次,并且仅在必要时深度(即,如果它根本没有被使用,它也根本不会被评估)。

f不是一个恒定的应用形式,因为它有参数;它相当于

f' = \a b -> let e1 = <lengthy computation>
in if a==b
then <simple computation>
else e1 + 2 * e1 - e1^2

所以,e1每次使用两个参数调用函数时都会计算一次。这可能也是您想要的,事实上,如果 <lengthy computation> 则可能是最好的行为取决于 ab 。如果它仅取决于 a ,你可以做得更好:

f₂ a = \b -> 
if a==b then <simple computation>
else e1 + 2 * e1 - e1^2
where e1 = <lengthy computation>

当您这样做时,此表单会更有效map (f 34) [1,3,9,2,9] :在该示例中,e1整个列表只会计算一次一次。 (但是 <lengthy computation> 不会在范围内包含 b,因此它不能依赖于它。)

OTOH,也可能存在您不希望的情况 e1完全保留。 (例如,如果它占用大量内存,但计算速度相当)。在这种情况下,您可以将其设为“无效函数”

f₃ a b
| a==b = <simple computation>
| otherwise = e1() + 2 * e1() - e1()^2
where e1 () = <lengthy computation>

默认情况下,函数不会被内存,因此在上面,<lengthy computation>如果 a==b 则完成零次以及其他三次。

另一种可能性是强制 e1总是只评估一次。您可以使用 seq 来做到这一点:

f₄ a b = e1 `seq` if a==b
then <simple computation>
else e1 + 2 * e1 - e1^2
where e1 = <lengthy computation>

这是唯一真正改变语义的建议,而不仅仅是性能:假设我们始终定义 e1 = error "too tough" 。然后f , f' , f₂f₃一切仍然有效,前提是 a==b ;然而f₄在这种情况下甚至会失败。

<小时/>

至于优化( -O-O2 ) - 这些通常不会改变程序的严格性属性(即不能在 ff₄ 的行为之间进行更改)。除此之外,编译器几乎可以自由地进行任何它认为对性能有益的更改。但通常,它不会改变我上面所说的任何内容。正如塔伦所说,主要的异常(exception)是 f₃ 。 :编译器将很容易内联e1 ()然后共享对计算值的引用,这可以防止垃圾收集器回收内存。所以最好不要依赖这种(无论如何有点黑客)技术。

关于haskell - `let`和 `where`表达式的结果会存储在haskell中吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43737684/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com