为什么值构造函数不能在不参数化类型的情况下获取类型变量?

时间:2012-05-24 21:59:04

标签: haskell

作为初学者,我不明白为什么不允许这样做:

data Pair = Pair a b

也就是说,为什么Pair 5 "foo"Pair 'C' []必须生成不同的类型?为什么不允许他们创建Pair类型的值?

我正在学习“了解你”,RWH和Haskell WikiBook,但却未能找到那种精确,不稳定的语言来描述我正在寻找的参数化类型。

2 个答案:

答案 0 :(得分:10)

从根本上说,问题是您没有关于Pair内容的信息。如果您只知道它包含任何类型的值,那么您可以在其上使用的唯一真实函数是id,这是非常无用的!

问题在于,由于每个值都可以是任何,因此您根本无法保证它们。所以你甚至无法使用==:如果值是函数怎么办?你无法比较函数的相等性!

想象一下,编写一个函数作用于您假设的Pair类型:

fn (Pair a b) = ...

您可以在ab使用哪些其他功能?

任何具有任何具体类型的内容(例如Int -> Int或其他内容)都无效,因为您无法判断a是否为Int。更复杂的类型如Num n => n -> n不起作用,因为您甚至不知道a是否为数字。 工作的唯一功能是具有t1 -> t1t1 -> t2类型的功能。但是,第一种类型的唯一合理函数是id,并且根本没有第二种类型的合理的函数。

现在,您可以说“我将尝试此功能,如果类型不起作用,则抛出错误。”但这将是动态类型,并且基本上会完全抛弃类型系统。这听起来很糟糕,但有时可能会有意义,所以你可以使用Data.Dynamic来完成类似的事情。但是,你不应该担心它作为一个初学者而且你永远不需要使用它 - 我到目前为止还没有。为了完整起见,我只是把它包括在内。

答案 1 :(得分:4)

使用存在类型语言扩展,您可以定义这样的类型:

{-# LANGUAGE ExistentialQuantification #-}

data Pair = forall a b. Pair a b

a, b :: Pair                                
a = Pair 1 2
b = Pair "abc" 'x'

此处ab的类型相同。

通常这不是以这种方式完成的,因为要对Pair执行任何有用的操作,您需要知道它包含的内容,而Pair的定义会删除所有信息。

所以你可以根据自己的需要创建这样的值,但是很难找到对它们有用的东西。