【发布时间】:2016-09-17 01:52:57
【问题描述】:
警告:非常初学者的问题。
我目前正在阅读我正在阅读的 Haskell 书中关于代数类型的部分,我遇到了以下示例:
data Id a =
MkId a deriving (Eq, Show)
idInt :: Id Integer
idInt = MkId 10
idIdentity :: Id (a -> a)
idIdentity = MkId $ \x -> x
好的,等一下。我不完全理解idIdentity 的例子。书中的解释是:
这有点奇怪。
Id类型接受一个参数和数据 构造函数MkId接受对应多态的参数 类型。因此,为了获得Id Integer类型的值,我们需要 将a -> Id a应用于Integer值。这将a类型变量绑定到Integer并在类型构造函数中应用(->),给我们Id Integer。我们还可以构造一个MkId值,它是一个身份 通过将a绑定到这两种类型的多态函数来实现函数 和术语级别。
但是等等。为什么只有完全多态的函数?我之前的理解是a可以是any类型。但显然受约束的多态类型不起作用:(Num a) => a -> a 在这里不起作用,并且 GHC 错误表明只有完全多态类型或“限定类型”(不确定它们是什么)是有效的:
f :: (Num a) => a -> a
f = undefined
idConsPoly :: Id (Num a) => a -> a
idConsPoly = MkId undefined
Illegal polymorphic or qualified type: Num a => a -> a
Perhaps you intended to use ImpredicativeTypes
In the type signature for ‘idIdentity’:
idIdentity :: Id (Num a => a -> a)
编辑:我是个笨蛋。正如@chepner 在下面的回答中指出的那样,我错误地写了下面的类型签名。这也解决了我在下面的下一句中的困惑......
回想起来,这种行为是有道理的,因为我没有为Id 定义Num 实例。但是,是什么解释了我能够在 idInt :: Id Integer 中应用像 Integer 这样的类型?
所以总的来说,我想我的问题是:类型构造函数的有效输入集具体是什么?只有完全多态的类型?那么什么是“合格类型”?等等……
【问题讨论】:
-
限定类型是那些有上下文的,即以
Constraint => ...开头的类型。约束是“资格”。 -
这篇关于 rank n 类型ocharles.org.uk/blog/guest-posts/2014-12-18-rank-n-types.html 的博客文章是了解合格类型和多态性的良好开端
标签: haskell functional-programming