haskell - 非多态函数的多态签名 : why not?

标签 haskell polymorphism

例如,考虑平凡函数

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

GHC 提示它无法推断 (b ~ Int)。该定义与签名相匹配,因为它返回的东西是 Integral(即 Int)。为什么 GHC 会/应该强制我使用更具体的类型签名?

谢谢

最佳答案

Haskell 中的类型变量是普遍量化的,所以 Integral b => b不仅仅意味着一些Integral类型,表示任意 Integral类型。换句话说,调用者可以选择应该使用哪些具体类型。因此,函数总是返回 Int 显然是类型错误。当类型签名说我应该能够选择任何 Integral类型,例如IntegerWord64 .

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

{-# LANGUAGE ExistentialQuantification #-}

data SomeIntegral = forall a. Integral a => SomeIntegral a

f :: a -> SomeIntegral
f x = SomeIntegral (3 :: Int)

使用此函数的代码必须具有足够多态性才能与任何 Integral 一起使用。类型。我们还必须使用 case 进行模式匹配而不是 let以防止 GHC 的大脑爆炸。
> case f True of SomeIntegral x -> toInteger x
3
> :t toInteger
toInteger :: Integral a => a -> Integer

在上面的例子中,你可以想到 x具有类型 exists b. Integral b => b ,即一些未知的Integral类型。

关于haskell - 非多态函数的多态签名 : why not?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9506173/

相关文章:

java - 双重 dispatch 和继承

haskell - 我应该阅读 Bird & Wadler 的 "Introduction to Functional Programming"的第一版还是第二版?

haskell - 数据类型是一对函数?

haskell - 如何使用 aeson 将 JSON 的非字符串部分保留为字符串?

java - 父类(super class)不调用重写的方法吗?

ruby-on-rails - Mongoid "reverse polymorphism"?如何在一个与类名不匹配的字段下嵌入多个类类型

haskell - 使用 `newtype` 包装其他类型

list - 在不改变列表的情况下对列表的所有元素取幂

java - 我们是否需要在命名约定方面区分接口(interface)类和抽象类?

c++ - 是否可以根据需要继续向基类(接口(interface))添加虚方法?