例如,考虑平凡函数

f :: (Integral b) => a -> b
f x = 3 :: Int

GHC提示它不能推论(b〜Int)。该定义与签名匹配,即它返回的是整数(即Int)。 GHC为什么/应该强制我使用更具体的类型签名?

谢谢

最佳答案

Haskell中的类型变量是通用量化的,因此Integral b => b不仅意味着Integral类型,还意味着任何Integral类型。换句话说,调用者可以选择应使用的具体类型。因此,当类型签名说我应该能够选择任何Int类型(例如IntegralInteger

有一些扩展允许您使用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类型。

09-25 22:24