为什么`[1," a"] :: [forall a。显示a => a]`是不允许的?

时间:2015-10-10 01:57:02

标签: haskell polymorphism typeclass existential-type higher-rank-types

在我(可能不正确)的理解中,以下两个列表应该是等效的:

[1, "a"] :: [forall a. Show a => a]

data V = forall a. Show a => V a
[V 1, V "a"] :: [V]

但是,第一个不被接受,但第二个工作正常(ExistentialQuantification)。

如果第一个列表不存在,那么map V :: ??? -> [V]的空白中的类型是什么?什么类型的机制强制存在包装器?

1 个答案:

答案 0 :(得分:13)

你的理解是对的。问题的一个重要部分是,您使用的传统存在量化语法对于那些不熟悉它的人来说非常混乱。因此,我强烈建议您使用GADT语法,这样做的好处还在于更强大。最简单的方法就是启用{-# LANGUAGE GADTs #-}。在我们处理它的同时,让我们开启{-# LANGUAGE ScopedTypeVariables #-},因为我讨厌想知道forall在任何给定位置的含义。您的V定义与

完全相同
data V where
  V :: forall a . Show a => a -> V

如果我们愿意,我们实际上可以删除显式的forall

data V where
  V :: Show a => a -> V

因此V数据构造函数是一个函数,它接受任何可显示类型的某些内容并生成V类型的内容。 map的类型非常严格:

map :: (a -> b) -> [a] -> [b]

传递给map的列表的所有元素必须具有相同的类型。所以map V的类型只是

map V :: Show a => [a] -> [V]

让我们现在回到你的第一个表达:

[1, "a"] :: [forall a. Show a => a]

现在实际上说的是[1, "a"]是一个列表,其每个元素都有forall a . Show a => a类型。也就是说,如果我提供任何a Show的实例,则列表的每个元素都应具有该类型。这是不正确的。例如,"a"没有Bool类型。这里还有另一个问题;类型[forall a . Show a => a]是" impredicative"。我不明白这意味着什么的细节,但是松散地说你已经在forall以外的类型构造函数的参数中插入了->,并且那个不允许。 GHC可能会建议您启用ImpredicativeTypes扩展,但这确实无法正常工作,所以您不应该这样做。如果需要存在量化事物的列表,则需要首先将它们包含在存在数据类型中或使用专门的存在列表类型。如果你想要一个普遍量化的东西列表,你需要先把它们包起来(可能是新类型的)。​​