什么是联合类型和交集类型?

时间:2013-07-17 04:32:49

标签: functional-programming programming-languages type-systems

什么是联合类型和交集类型?

我咨询了this question,但有些小型工作类型系统 会更好,而不是必要的实用。

具体来说,通过联合类型,我指的是mentioned in this blog post 而不是和类型,其中伪代码看起来像

{String, null} findName1() {
  if (...) {
    return "okay";
  } else {
    return null;
  }
}

wikipedia page对交集类型和联合有一个简短的解释 类型,但似乎没有进一步的参考。

3 个答案:

答案 0 :(得分:9)

联合和交集类型只是将类型视为值集(大多数是无限集)。如果您正在考虑类型,则可以将对集合(值集)的任何操作应用于类型(值集)以创建新类型(值集),至少在概念上如此。

联合类型在某种意义上类似于总和类型,您似乎熟悉它。事实上,我经常听到描述为“歧视联盟”类型的和类型。基本区别在于,类似(Haskell表示法)data FooBar = Foo Integer | Bar String的和类型允许您判断给定的FooBar值是包含Integer还是String(因为{{1} } {标记为FooBarFoo)。即使我们写两个类型相同的Bar,“标记”也会添加额外的信息,我们可以告诉“{1}}值的”整数“。

类似于union的类型(不是有效的Haskell)data FooBar = Foo Integer | Bar IntegerFooBar中的值只是所有字符串值和所有整数值。如果我们创建一个与data FooBar = Integer | String相同的两种类型的联合类型,它应该在逻辑上与FooBar无法区分,因为集合与其自身的联合本身就是。

原则上,你可以用类型U中的值来做的事情是类型A和B的联合,它们只是处理As的操作,也适用于Bs;任何仅适用于As或Bs的操作可能会得到错误的输入,因为U没有信息可以说是A还是B. 1

(Uadisciminiminated)联合类型在类型系统类似于Haskell的语言中不会非常有趣,因为具体类型是不相交的 2 ,因此对As和Bs都有效的唯一操作所有值(除非A是B,其中只是对该单一类型起作用的所有操作)。

但在某种程度上,类型类(如果你熟悉它们)是一种提供类似联合类型的东西的方法。一个多态但被约束为某个类型类的成员的类型有点像类型类中所有类型的并集(除了你不知道它们是什么,因为类型类原则上是开放的);您可以使用这样的值做的唯一事情是已声明处理类型类中每个类型值的变量。

联合类型在使用子类型的语言中可能很有趣(在面向对象的编程语言中很常见)。如果你将一个普通超类型的两个子类型联合在一起,你得到的东西至少支持超类型的操作,但是它排除了超类型的任何其他子类型,所以它与使用超类型。

交集类型正是这个概念,但使用交集而不是联合。这意味着您可以使用类型I中的值进行操作,即类型A和B的交集,这些操作对As 加上的操作起作用于Bs;我保证的任何东西都是A和B,因此它可以安全地用于任何一种操作。

在使用类似Haskell的类型系统的语言中,这些也不会非常有趣。因为具体类型是不相交的 2 ,所以任何非平凡的交​​叉都是空的。但同样,类型类约束可以提供类似交集类型的东西;如果向同一个类型变量添加多个类型类约束,那么在期望该类型变量的地方可以使用的唯一值是所有类型类的“交集”中的类型,以及可以在这些值是适用于任何类型类的操作。


1 你可以想象将一个操作data FooBar = Integer | Integer和一个操作Integer结合起来得到一个操作A -> C,就像你可以使用sum类型的标签一样将总和类型“路由”到适当的操作。但对于完全普遍的联盟类型来说,它变得模糊不清如果A和B重叠(并且只要你有联合类型,重叠类型就会进入战斗),那么你在重叠区域中的某个值上调用哪个操作?如果您可以判断它是A还是B,那么您确实得到了一个和类型而不是一个联合类型,并且如果您应用一些任意分辨率策略,例如选择B -> D操作,因为(A | B) -> (C | D)是在联合类型的定义中前面列出的,然后在简单的情况下工作正常,但是如果你有类似A -> C的类型(我使用A表示交集),则会非常混乱。

2 虽然“不相交类型”这一点值得商榷。在类似(A | B) & (B | A)的类型中,即使对于不同的&,您也可以合理地认为data Maybe a = Nothing | Just a是“相同的值”。如果是,那么Nothinga的联合只包含一个Maybe String(而不是Maybe Integer,即“无字符串”和Nothing是“没有整数”)。 NothingNothing的交集只包含一个值,即Maybe String

答案 1 :(得分:2)

Whiley programming language支持联合和交集类型。如果将类型视为集合(即类型int是所有有效整数的集合),则union类型对应于set union,而交集类型则用于设置交集。

联合类型的Whiley中的经典示例表示“可为空”类型,如下所示:

null|int indexOf(string str, char c):
    for i in 0..|str|:
       if str[i] == c:
          return i // found a match
    // didn't find a match
    return null

此处,类型null|int可以包含任何有效整数或特殊null值。在Whiley中,您无法对此类型执行算术运算。因此,首先必须键入test以检查null值,然后才能使用返回的值。例如,像这样:

string replaceFirst(string str, char old, char new):
    idx = indexOf(str,old)
    if idx is int:
        str[idx] = new
    // return potentially updated string
    return str

我在Whiley herehere上写了一些关于联合类型的帖子。交叉点类型类似,但编译器目前尚未得到很好的支持。

答案 2 :(得分:1)

可以将类型视为一组值。例如,如果Boolean是值truefalse的集合,则表示某个值的类型为Boolean,则表示值为truefalse

请注意,某些类型(如String)可能具有无限多个可能的值。

您可能知道,union和intersection是set操作,因此它们也适用于类型。例如,当一个人有类型T1 = {男,女}和T2 = {不适用}时,可以建立类型T3 = T1 \ union T2 = {男,女,不适用}。这种类型有用的一个例子是问题的答案:“你的第一个孩子的性别是什么?”由于有些人没有孩子,他们可以回答:不适用。