gpt4 book ai didi

haskell - Haskell 中的求值是如何工作的,对于有约束的表达式

转载 作者:行者123 更新时间:2023-12-02 02:44:04 24 4
gpt4 key购买 nike

假设我用 GHCi 写:

GHCi> let x = 1 + 2 :: Integer
GHCi> seq x ()
GHCi> :sprint x

GHCi 打印 x = 3正如自然所料。

然而,
GHCi> let x = 1 + 2
GHCi> seq x ()
GHCi> :sprint x

yield x = _
两个表达式之间的唯一区别是它们的类型( IntegerNum a => a )。我的问题是究竟发生了什么,为什么看起来是 x未在后一个示例中进行评估。

最佳答案

主要问题是

let x = 1 + 2

定义类型 forall a. Num a => a 的多态值,这是一个类似于函数的评估结果。

每次使用 x可以制成不同的类型,例如 x :: Int , x :: Integer , x :: Double等等。这些结果不会以任何方式“缓存”,而是每次都重新计算,好像 x是一个被多次调用的函数,可以这么说。

确实,类型类的常见实现实现了这样的多态 x作为函数
x :: NumDict a -> a

哪里 NumDict a上面的参数是编译器自动添加的,带有 a的信息。成为 Num类型,包括如何执行加法,如何解释内部的整数文字 a , 等等。这称为“字典传递”实现。

因此,使用多态 x多次确实对应于多次调用一个函数,导致重新计算。为了避免这种情况,Haskell 中引入了(可怕的)单态限制,迫使 x改为单态。 MR 不是一个完美的解决方案,在某些情况下会产生一些令人惊讶的类型错误。

为了缓解这个问题,在 GHCi 中默认禁用 MR,因为在 GHCi 中我们不太关心性能——可用性在那里更为重要。然而,正如您发现的那样,这会导致重新计算重新出现。

关于haskell - Haskell 中的求值是如何工作的,对于有约束的表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60971733/

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