Haskell - 非法多态类型?

时间:2015-01-12 04:14:02

标签: haskell

为什么这种类型的单一用法编译,但将其放入列表失败?

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]

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

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'

1 个答案:

答案 0 :(得分:12)

这种对Haskell类型系统的限制是为了简化类型推断和检查。具有预测秩-1类型的类型推断(见下文)是可判定的并且具有相对简单的实现。具有rank-2类型的类型推断是可判定的但非常复杂,以至于我不知道任何具有rank-2类型推断的实现的语言。 3级及以上类型的类型推断是不可判定的。令人印象深刻的类型也使事情变得复杂; GHC曾经有一个实现,它允许使用impredicative类型进行类型检查(以及一些非常有限的推断),但是它太复杂了以至于后来被删除了。 (目前GHC仍然接受了一些只有使用impredicative类型进行类型检查的值,但我认为这不是一个"稳定的特征。)

快速定义:排名-1类型具有所有量化和类约束"外部"类型,所以所有rank-1类型都是

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

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

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