类型构造函数和类型常量(和类型变量):有什么区别?

时间:2012-02-04 08:34:49

标签: haskell types

我对类型构造函数,类型常量和类型变量之间的区别感到困惑。

The Haskell 98 report表示有4种类型的表达式:

  1. 输入变量
  2. 类型构造函数
  3. 输入申请
  4. 括号类型
  5. 那么什么是类型常量?报告说“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代表什么? TyvarTVar怎么样?为什么需要单独TTy

3 个答案:

答案 0 :(得分:7)

上一个问题

  

显然Tycon代表“类型构造函数”,但TCon代表什么? Tyvar和TVar怎么样?为什么需要分开T和Ty?

第一

TConTVar等中的'T'只是关注类型的标记,它们是Type类型的构造函数。 TCon采用Tycon类型的值,并从中构造Type类型的值。Type的构造函数不以Ty为前缀,而是仅T以避免混淆,可以定义类型

data Type = Tyvar Tyvar | Tycon Tycon | ...

因为值构造函数和类型存在于不同的名称空间中,但这会为更加混乱开辟道路。

1输入变量

是可以用其他类型表达式替换的类型表达式,它们的标识符以小写字母开头(或者它们可以是不以':'开头的符号)。

2类型构造函数

是带有零个或多个类型表达式参数的类型表达式,用于构造类型*的类型,例如

  • 内部
  • 字符

是nullary类型构造函数,它们使用零类型表达式参数来构造类型*的类型,这些也是类型常量。

  • 也许
  • IO
  • []

是一元类型构造函数,它们采用一种类型表达式(在这些示例中类型*,但是一元类型构造函数也可以接受其他类型的参数)。

  • 要么
  • (,)

是二进制类型构造函数,

  • StateT

是一个三元类型的构造函数,它带有两个类*和一个* -> *类型的参数(StateT的类型是StateT :: * -> (* -> *) -> * -> *)。

3输入申请

t1 t2形式的类型表达式。如果t2具有种类k2t1具有种类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”)。它将TyconTyvar的定义分解为单独的类型定义的原因可能是它们被某些代码单独使用。

答案 2 :(得分:1)

  

第二种类型的表达式是“构造函数”还是“常量”?

没有理由感到困惑。

看,我们可以说5是一个值构造函数,因为它构造了值5.同时我们可以说5是一个常量。

另一个例子:在Maybe类型中我们有

data Maybe a = Just a | Nothing

JustNothing都是值构造函数。很容易理解Nothing也是常数。可能更难理解Just也是一个常量:它表示一个函数,给定任何值,构造一个Maybe类型的值。如果您发现难以理解,请想象使用Just的程序内存中会有一些机器代码实际执行构造Maybe值的任务。此代码永远不会更改,因此它是常量,Just是我们引用此常量的方式。

现在我们理解常量构造函数在值的范围内意味着什么,我们可以将它扩展到类型领域。