懒惰的数据结构评估

时间:2014-07-25 18:48:41

标签: haskell lazy-evaluation

我正在读关于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 = _

当我们在没有y的情况下尝试时,为什么_值为(_, _)而非::Int

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

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

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

谢谢。

1 个答案:

答案 0 :(得分:7)

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

1 + 1

这是因为GHCi选择> let x :: Num a => a | x = 1 + 1 > x 2 > :sprint x x = _ 作为Integer的默认类型,但是当它执行此操作时,它不会将结果存储在Num的内存位置,因为那里不是一种知道这是否是正确答案的方法。这就是为什么您从x看到x = _,它实际上没有评估:sprint,而是评估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 了!请记住,您可能永远不会使用GHC的这项功能,但最好了解一下。