【问题标题】:Lazy evaluations of data structures数据结构的惰性评估
【发布时间】:2014-07-25 18:48:41
【问题描述】:

我正在阅读有关 haskell 中的惰性评估的信息,并有一个问题。例如我们有以下计算:

Prelude> let x = 1 + 1 :: Int
Prelude> let y = (x,x)

得到x的值后:

Prelude> :sprint x
x = _

这是未经评估的。好的,现在让我们获取 y 的值:

Prelude> :sprint y
y = (_,_)

它也没有被评估,因为y 依赖于x and it's unevaluated。现在让我们试试同样的例子,但没有::Int:

Prelude> let x = 1 + 1
Prelude> let y = (x, x)
Prelude> :sprint y
y = _

当我们尝试不使用::Int 时,为什么y 的值是_ 而不是(_, _)?

我看到它们有不同的类型:

Prelude> let x = 1 + 1
Prelude> :t x
x :: Num a => a
Prelude> let x = 1 + 1 :: Int
Prelude> :t x
x :: Int

但是为什么y 的值取决于它呢?

谢谢。

【问题讨论】:

  • 现在是真正有趣的部分,x 的类型为Num a => a,在您全面评估x 和y 之后会发生什么?他们的:sprint 代表会怎样?
  • @bheklilr,是的,非常有趣。我做了:seq 用于 x 和 y,它们打印值,但 :sprint 打印 _
  • 当x 的类型是Num a => a 时,它甚至意味着什么?编译器如何知道如何处理它?当它不知道要使用+ 的哪个实现时,它怎么能说x 的值是2?我可以在Int 周围实现我自己的新类型,将+ 定义为(MyInt x) + (MyInt y) = MyInt (x - y),那么GHC 在这里做什么才能打印x 的值2?
  • 它不可能知道使用Num 的哪个实例来打印它,对吧?那么你认为它在做什么呢?如果您正在编写 GHCi 并希望能够打印出 Num a => a 类型的值,并且假设没有人会邪恶到将 + 定义为 -,您会怎么做?我知道我只会选择一个健全的默认值来“评估”它,但实际上不会将该结果存储在变量的内存位置
  • @CarstenKönig 这发生在我的 GHC 中。如果y :: Num a => (a, a),那么它甚至无法评估y WHNF(我认为?),所以它的thunk 是_,而不是(_, _)。你可能有MonomorphismRestriction 吗?自从我将 GHCi 配置为默认禁用它以来,我还没有测试过它。

标签: haskell lazy-evaluation


【解决方案1】:

发生的情况是,当您将x 指定为Num a => a 类型时,编译器不可能知道在执行1 + 1 时要使用Num 的哪个实例。它的作用是使用默认值。 GHC 为某些类型类定义了默认类型,因此当无法确定使用哪种具体类型时,它仍然可以提供有意义的结果而不会引发错误。所以当你看到

> let x :: Num a => a
|     x = 1 + 1
> x
2
> :sprint x
x = _

这是因为 GHCi 选择 Integer 作为 Num 的默认类型,但是当它执行此操作时,它不会将结果存储在 x 的内存位置,因为没有办法知道这是否是正确的答案。这就是为什么你从:sprint 看到x = _,它实际上并没有评估x :: Num a => a,而是评估了x :: Integer。你甚至可以自己弄乱这个默认值:

> newtype MyInt = MyInt Int deriving (Eq)
>
> instance Show MyInt where
|     show (MyInt i) = show i
> instance Num MyInt where
|     (MyInt x) + (MyInt y) = MyInt (x - y)
|     fromInteger = MyInt . fromInteger
>
> default (MyInt)
> x
0

所以现在我们已经说过1 + 1 = 0!请记住,您可能永远不会使用 GHC 的此功能,但了解一下是很好的。

【讨论】:

  • btw:在我的系统上,GHCi 在评估后会将x 设置为2 :: Integer!
猜你喜欢
  • 1970-01-01
  • 2014-02-08
  • 2013-03-11
  • 2017-01-18
  • 2018-11-11
  • 2015-05-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多