在玩 Haskell 时遇到了这个问题,我很困惑:
Hugs> :type (\x -> x^2)
\x -> x ^ 2 :: (Integral a, Num b) => b -> b
里面在做什么a
?我该怎么读?如果我在 GHCi 中输入相同的内容,它会给出我期望的输出:
Prelude> :type (\x -> x^2)
(\x -> x^2) :: Num a => a -> a
这是拥抱中的错误吗?
Integral
约束来自 的指数2
。请记住,在 Haskell 中,整数文字实际上是 type 的多态值Num a => a
。然后编译器推断,由于它被用作 的指数(^) :: (Num a, Integral b) => a -> b -> a
,它必须是更受约束的类型Integral a => a
。
为了让您不必在整个代码中消除数字文字的歧义,Haskell 使用类型默认来为任何不受约束的数字类型选择合理的具体类型。在这种情况下,那将是Integer
. 不同之处似乎在于:type
Hugs 报告了在此发生之前推断的类型,而 GHCi 报告了应用类型默认值之后的类型。
如果您自己为指数指定具体类型,额外的约束就会消失。
Hugs> :type (\x -> x^(2 :: Integer))
\x -> x ^ 2 :: Num a => a -> a
这是一种推测,但这可能与(^)
. :t (^)
在 ghci 返回(^) :: (Num a, Integral b) => a -> b -> a
。我猜 hugs 认为的第二个参数^
需要是一个Integral
,即使那个参数只是一个常量 2,它也包含类型签名中的约束。