在玩 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. 不同之处似乎在于:typeHugs 报告了在此发生之前推断的类型,而 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,它也包含类型签名中的约束。