非多态函数的多态签名:为什么不呢?

时间:2012-02-29 20:33:28

标签: haskell polymorphism

举个例子,考虑一下琐碎的函数

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

GHC抱怨它不能推断(b~Int)。该定义匹配签名,因为它返回的是Integral(即Int)。为什么GHC会强迫我使用更具体的类型签名?

由于

3 个答案:

答案 0 :(得分:17)

Haskell中的类型变量是普遍量化的,因此Integral b => b并不仅仅意味着某些 Integral类型,它意味着任何 {{1 }类型。换句话说,调用者可以选择应该使用哪种具体类型。因此,当类型签名说我应该能够选择任何Integral类型时,函数总是返回Int,这显然是一个类型错误。 IntegralInteger

有一些扩展允许你使用existentially quantified type variables,但它们使用起来比较麻烦,因为它们需要一个包装类型(为了存储类型类字典)。大多数时候,最好避免它们。但如果你确实想使用存在类型,它看起来像这样:

Word64

使用此函数的代码必须具有足够的多态性才能使用任何{-# LANGUAGE ExistentialQuantification #-} data SomeIntegral = forall a. Integral a => SomeIntegral a f :: a -> SomeIntegral f x = SomeIntegral (3 :: Int) 类型。我们还必须使用Integral而不是case来模式匹配,以防止GHC的大脑爆炸。

let

在上面的示例中,您可以将> case f True of SomeIntegral x -> toInteger x 3 > :t toInteger toInteger :: Integral a => a -> Integer 视为具有x类型,即某种未知exists b. Integral b => b类型。

答案 1 :(得分:2)

您函数的最常见类型是

f :: a -> Int

使用类型注释,您只能要求您想要更多特定类型,例如

f :: Bool -> Int

但您无法声明 less 特定类型。 Haskell类型系统不允许您进行代码无法保证的承诺。

答案 2 :(得分:0)

正如其他人所说,在Haskell中,如果函数返回类型为x的结果,则意味着调用者决定实际类型是什么。不是功能本身。换句话说,该函数必须能够返回与签名匹配的任何可能类型

这与大多数OOP语言不同,这样的签名意味着函数可以选择它返回的内容。显然这让一些人感到困惑......