我正在读关于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
的值取决于它?
谢谢。
答案 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的这项功能,但最好了解一下。