我对类型构造函数,类型常量和类型变量之间的区别感到困惑。
The Haskell 98 report表示有4种类型的表达式:
那么什么是类型常量?报告说“Char,Int ...是类型常量”但我找不到更详细的例子。更令人困惑的是IO
首先被称为“一元类型构造函数”,但后来被称为“常量,IO”。
我问的原因是因为paper on Haskell's type system implementation。在其中,它说:
Haskell类型表达式是类型变量或常量(每个都具有关联的类型),或者是一种类型的应用程序:应用类型k1 - > k2到类型k1产生类型k2
它说的不同于报告。 第二种类型的表达式是“构造函数”还是“常量”?
该文件还包括显示代表性的代码:
data Type = TVar Tyvar | TCon Tycon | TAp Type Type | TGen Int
deriving Eq
data Tyvar = Tyvar Id Kind
deriving Eq
data Tycon = Tycon Id Kind
deriving Eq
显然Tycon
代表“类型构造函数”,但 TCon
代表什么? Tyvar
和TVar
怎么样?为什么需要单独T
和Ty
?
答案 0 :(得分:7)
上一个问题
显然Tycon代表“类型构造函数”,但TCon代表什么? Tyvar和TVar怎么样?为什么需要分开T和Ty?
第一
TCon
,TVar
等中的'T'只是关注类型的标记,它们是Type
类型的构造函数。 TCon
采用Tycon
类型的值,并从中构造Type
类型的值。Type
的构造函数不以Ty
为前缀,而是仅T
以避免混淆,可以定义类型
data Type = Tyvar Tyvar | Tycon Tycon | ...
因为值构造函数和类型存在于不同的名称空间中,但这会为更加混乱开辟道路。
1输入变量
是可以用其他类型表达式替换的类型表达式,它们的标识符以小写字母开头(或者它们可以是不以':'开头的符号)。
2类型构造函数
是带有零个或多个类型表达式参数的类型表达式,用于构造类型*
的类型,例如
是nullary类型构造函数,它们使用零类型表达式参数来构造类型*
的类型,这些也是类型常量。
是一元类型构造函数,它们采用一种类型表达式(在这些示例中类型*
,但是一元类型构造函数也可以接受其他类型的参数)。
是二进制类型构造函数,
是一个三元类型的构造函数,它带有两个类*
和一个* -> *
类型的参数(StateT
的类型是StateT :: * -> (* -> *) -> * -> *
)。
3输入申请
是t1 t2
形式的类型表达式。如果t2
具有种类k2
且t1
具有种类k2 -> k3
(类似于功能应用),则它只是格式良好。例如,StateT s
是类型应用程序,类型表达式StateT
应用于类型变量s
。
4括号类型
是括号中的类型表达式,可能是优先级解析或解析所必需的,否则它与未表示的类型表达式相同,例如在
中instance Monad (Either e) where ...
括号类型表达式(Either e)
与Either e
相同,但必须使用括号将其与两个类型表达式Either
的两参数类的实例区分开来e
。在类型
StateT s ((->) a) b
(->) a
周围的括号是为了优先。 (注意,类型构造函数(->)
是类型构造函数以大写字母开头的一般规则未涵盖的特殊情况,如[]
,(,)
,(,,)
等。 )
现在,输入常量。这些只是不包含类型变量的类型表达式,但我不认为它在任何地方都是正式定义的。因此,只有大写标识符(包括以':'开头的符号)和特殊情况([]
,(->)
,(,)
,...)的任何类型表达式都是一个类型常量。< / p>
答案 1 :(得分:7)
在类型理论中,“类型构造函数”通常是指更高类型的类型表达式。通过扩展,普通类型通常作为退化情况包括在内。
在编程语言中,“类型构造函数”通常用于更具体的含义,指的是由上下文定义的命名的类型构造函数。同样,这可以包括普通类型作为零参数的退化情况。
术语“类型常数”稍微不那么标准。在Haskell定义中,它似乎非常非正式地使用,并且可能意味着表示由语言预定义的命名类型构造函数的子集(与用户定义的类型构造函数相对,它是根据代数定义的)类型和预定义类型构造函数)。因此,每个常量也是一个类型构造函数。
对于“T”vs“Ty”,这似乎是您正在查看的代码段中的命名约定,旨在区分语言级数据构造函数(“T”)和语言级类型施工人员(“Ty”)。它将Tycon
和Tyvar
的定义分解为单独的类型定义的原因可能是它们被某些代码单独使用。
答案 2 :(得分:1)
第二种类型的表达式是“构造函数”还是“常量”?
没有理由感到困惑。
看,我们可以说5
是一个值构造函数,因为它构造了值5.同时我们可以说5是一个常量。
另一个例子:在Maybe类型中我们有
data Maybe a = Just a | Nothing
Just
和Nothing
都是值构造函数。很容易理解Nothing
也是常数。可能更难理解Just
也是一个常量:它表示一个函数,给定任何值,构造一个Maybe
类型的值。如果您发现难以理解,请想象使用Just
的程序内存中会有一些机器代码实际执行构造Maybe
值的任务。此代码永远不会更改,因此它是常量,Just
是我们引用此常量的方式。
现在我们理解常量和构造函数在值的范围内意味着什么,我们可以将它扩展到类型领域。