例如,考虑平凡函数
f :: (Integral b) => a -> b
f x = 3 :: Int
GHC提示它不能推论(b〜Int)。该定义与签名匹配,即它返回的是整数(即Int)。 GHC为什么/应该强制我使用更具体的类型签名?
谢谢
最佳答案
Haskell中的类型变量是通用量化的,因此Integral b => b
不仅意味着Integral
类型,还意味着任何Integral
类型。换句话说,调用者可以选择应使用的具体类型。因此,当类型签名说我应该能够选择任何Int
类型(例如Integral
或Integer
。
有一些扩展允许您使用existentially quantified type variables,但是它们使用起来比较麻烦,因为它们需要包装类型(以便存储类型类字典)。大多数时候,最好避免使用它们。但是,如果您确实想使用存在性类型,它将看起来像这样:
{-# LANGUAGE ExistentialQuantification #-}
data SomeIntegral = forall a. Integral a => SomeIntegral a
f :: a -> SomeIntegral
f x = SomeIntegral (3 :: Int)
然后,使用此函数的代码必须足够多态才能与任何
Word64
类型一起使用。我们还必须使用Integral
而不是case
进行模式匹配,以防止GHC的大脑爆炸。> case f True of SomeIntegral x -> toInteger x
3
> :t toInteger
toInteger :: Integral a => a -> Integer
在上面的示例中,您可以认为
let
具有x
类型,即某种未知的exists b. Integral b => b
类型。