作为初学者,我不明白为什么不允许这样做:
data Pair = Pair a b
也就是说,为什么Pair 5 "foo"
和Pair 'C' []
必须生成不同的类型?为什么不允许他们创建Pair
类型的值?
我正在学习“了解你”,RWH和Haskell WikiBook,但却未能找到那种精确,不稳定的语言来描述我正在寻找的参数化类型。
答案 0 :(得分:10)
从根本上说,问题是您没有关于Pair
内容的信息。如果您只知道它包含任何类型的值,那么您可以在其上使用的唯一真实函数是id
,这是非常无用的!
问题在于,由于每个值都可以是任何,因此您根本无法保证它们。所以你甚至无法使用==
:如果值是函数怎么办?你无法比较函数的相等性!
想象一下,编写一个函数作用于您假设的Pair
类型:
fn (Pair a b) = ...
您可以在a
和b
使用哪些其他功能?
任何具有任何具体类型的内容(例如Int -> Int
或其他内容)都无效,因为您无法判断a
是否为Int
。更复杂的类型如Num n => n -> n
不起作用,因为您甚至不知道a
是否为数字。 工作的唯一功能是具有t1 -> t1
或t1 -> 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'
此处a
和b
的类型相同。
通常这不是以这种方式完成的,因为要对Pair
执行任何有用的操作,您需要知道它包含的内容,而Pair
的定义会删除所有信息。
所以你可以根据自己的需要创建这样的值,但是很难找到对它们有用的东西。