在GHCi中,我输入
let xs = [1, 'a']
它立即抱怨错误:
<interactive>:28:11:
No instance for (Num Char) arising from the literal ‘1’
In the expression: 1
In the expression: [1, 'a']
In an equation for ‘xs’: xs = [1, 'a']
然而,当我输入
时let xs = [1, [1, 1]]
它刚过去了。当我尝试打印xs时,它会抱怨:
<interactive>:5:1:
No instance for (Num [t0]) arising from a use of ‘it’
In a stmt of an interactive GHCi command: print it
我认为Haskell是一种静态类型语言,因此任何类型错误都应该在编译时捕获。我想知道为什么在不同时间捕获上述2个错误?
答案 0 :(得分:8)
1
是Num a => a
类型的多态值。所以在[1, [2, 3]]
中,我们有[2, 3] :: Num a => [a]
;由于所有列表元素必须具有相同的类型,因此我们得出结论:我们必须具有1 :: Num a => [a]
。这有点奇怪 - 将1
视为具有列表类型是奇怪的 - 但如果有人创建了一个足够奇怪的Num
实例,则可以完全有效。在您尝试使用实例之前,将检查是否存在实例;这使您有机会在使用实例定义值后定义实例。因此,在您尝试使用列表[1, [2, 3]]
实际执行某些操作之前,它不会抱怨。
为了说明我的意思,可以写一下:
instance Num a => Num [a] where
fromInteger n = pure (fromInteger n)
(+) = liftA2 (+)
(-) = liftA2 (-)
(*) = liftA2 (*)
abs = liftA abs
signum = liftA signum
(事实上,这个实例适用于任何Applicative
,偶尔也会有用。)然后,在ghci:
> let xs = [1, [1, 1]]
> xs
[[1],[1,1]]
见ma,没有错误!