【问题标题】:Haskell - Illegal Polymorphic type?Haskell - 非法多态类型?
【发布时间】:2015-01-12 04:14:01
【问题描述】:

为什么单次使用这种类型可以编译,但是放入列表却失败了?

ft1  :: (Foldable t, Num a) => t a -> a
ft1   =   (F.foldl (+)  0)

fTest :: [(Foldable t, Num a) => t a -> a ]
fTest = [ F.foldl (+)  0 ]

后者给出错误:

folding.hs:80:10:
    Illegal polymorphic or qualified type:
      (Foldable t, Num a) => t a -> a
    Perhaps you intended to use ImpredicativeTypes
    In the type signature for `fTest':
      fTest :: [(Foldable t, Num a) => t a -> a]

同样,尝试命名它失败(不同):

type Ftst t a = (Foldable t, Num a) => t a -> a

folding.hs:80:1:
    Illegal polymorphic or qualified type:
      (Foldable t, Num a) => t a -> a
    Perhaps you intended to use RankNTypes or Rank2Types
    In the type declaration for `Ftst'

【问题讨论】:

  • 猜测:也许你的意思是fTest :: (Foldable t, Num a) => [t a -> a]
  • 谢谢;我以为我已经尝试过了,但它确实有效。然而仍然尝试使用类型别名(如上面的 Ftst)命名相同的类型失败(有或没有列表符号) - 为什么?

标签: haskell


【解决方案1】:

对 Haskell 类型系统的这种限制是为了简化类型推断和检查。具有谓词 rank-1 类型(见下文)的类型推断是可判定的,并且具有相对简单的实现。 rank-2 类型的类型推断是可确定的,但相当复杂,以至于我不知道任何具有 rank-2 类型推断实现的语言。等级 3 及以上类型的类型推断完全无法确定。暗示类型也使事情变得相当复杂。 GHC 曾经有一个实现,它允许类型检查(以及一些非常有限的推理)与禁言类型,但它太复杂以至于后来被淘汰了。 (目前,GHC 仍然接受一些仅对非谓语类型进行类型检查的值,但我认为这不是一个“稳定”的特性。)

快速定义:rank-1 类型具有“外部”类型的所有量化和类约束,因此所有 rank-1 类型都具有以下形式

forall a_1 ... a_m. (C_1, ..., C_n) => t

Rank-2 类型允许函数参数具有 rank-1 类型;一般来说,rank n 类型允许函数参数具有 rank (n-1) 类型。

预测性回答了哪些类型可以替代类型变量的问题。如果只能替换单态类型(尽管可能带有类型变量!),那么您就处于谓词系统中; impredicative 类型允许您用多态类型替换类型变量。通过扩展,谓词系统中的参数数据类型只能接受单态类型作为参数。因此,例如,将[] 类型构造函数应用于forall t a. (Foldable t, Num a) => t a -> a 类型的示例试图将构造函数应用于多态类型,因此仅在谓语系统中有效。

【讨论】:

  • 谢谢,我以前没有尝试过,这很有帮助。有趣的是,将量化移到列表构造函数之外确实有效(上面的 cmets)。副手这似乎是同一个问题 - 将列表构造函数应用于多态类型,只是声明不同。我不清楚为什么即使这种调整后的形式 (Foldable t, Num a) => [t a -> a] 也可以用于类型签名,但不能用于类型别名。
  • @guthrie 区别在于上下文(Foldable t, Num a)(需要隐式forall)是在列表类型构造函数内部还是外部。至于类型别名,因为它们可以出现在任何地方(包括作为函数参数的类型),所以它们必须是单态的,所有结果类型才能排名 1。
猜你喜欢
  • 2018-01-11
  • 1970-01-01
  • 2017-01-14
  • 2012-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多