gpt4 book ai didi

haskell - 这些表达式求值时的奇怪重用

转载 作者:行者123 更新时间:2023-12-02 14:22:42 25 4
gpt4 key购买 nike

我尝试使用 Debug.Trace.trace 来计算函数被评估的次数,并看到一些令人惊讶的结果。

ghci> import Debug.Trace

ghci> let x = (trace " Eval'd!" (* 2)) 3 in (x, x)
( Eval'd!
6, Eval'd!
6)

ghci> let x = (trace " Eval'd!" (* 2)) 3 in x `seq` (x, x)
Eval'd!
( Eval'd!
6, Eval'd!
6)

ghci> let x = (trace " Eval'd!" (* 2)) (3 :: Int) in (x, x)
( Eval'd!
6,6)

我假设每次对 (* 2) 函数求值时都会打印一次 Eval'd 。这是一个正确的假设吗?

其次,为什么该函数会多次打印?我怀疑 xNum 类型类的某种未指定类型与此有关,因为第三种情况有效,但我想不出解释。

(x, x)::Num a => (a, a) 保证元组的两个元素具有与 (x, x) 相同的值::(Int, Int),那么为什么要 eval x 两次呢?

更新:

实际上我假设(x, x)的类型是Num a => (a, a)。但显然是 (x, x)::(Num t, Num t1) => (t, t1)

为什么 GHC 没有意识到这里的 t ~ t1 ?我怀疑这与我的问题的答案有关。

最佳答案

它们保证是同一类型:

Prelude Debug.Trace> :t let x = (trace " Eval'd!" (* 2)) 3 in (x, x)
let x = (trace " Eval'd!" (* 2)) 3 in (x, x)
:: (Num t, Num t1) => (t, t1)

此外,如果将其放入文件中,即使从 GHCi 调用,它也只会被评估一次。 (这是因为在文件声明中,但在 GHCi 中声明时,dreaded monomorphism restriction 默认处于启用状态):

import Debug.Trace
main = print $ let x = (trace " Eval'd!" (* 2)) 3 in (x, x)

另外,

let x = (trace " Eval'd!" 6) in (x,x)

行为大致相同,所以这实际上都是类型(类)的歧义。

它之所以不共享 x 的所有用途,是因为在 GHC 核心级别 x 未经优化,实际上是一个函数采用 Num 类型类字典参数。要共享它,它必须进行足够的分析以确保类型是相同的。

它没有意识到的原因基本上是,GHCi 的目的是为了快速的代码实验周转,而不是为了创建好的代码,所以它几乎没有做任何优化全部,所以这几乎纯粹是运气它是否检测到此类事情。

(GHCi 字节码设计中还有一个 outstanding hole,这意味着您无法为其启用优化级别,即使您愿意。基本上它不支持“拆箱元组” ,GHC 优化大量使用。)

关于haskell - 这些表达式求值时的奇怪重用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32423526/

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