Functional programming 什么是并集类型和交集类型?

Functional programming 什么是并集类型和交集类型?,functional-programming,programming-languages,type-systems,Functional Programming,Programming Languages,Type Systems,什么是并集类型和交集类型 我曾咨询过,但有些小型工作型系统 会更好,不需要实际的 具体地说,根据联合类型,我指的是 而不是sum类型,伪代码如下所示 {String, null} findName1() { if (...) { return "okay"; } else { return null; } } 对交叉点类型和并集进行了简要说明 类型,但似乎没有关于此的进一步参考。类型可以看作是一组值。例如,如果Boolean是值true和false的集合,则表示某个

什么是并集类型和交集类型

我曾咨询过,但有些小型工作型系统 会更好,不需要实际的

具体地说,根据联合类型,我指的是 而不是sum类型,伪代码如下所示

{String, null} findName1() {
  if (...) {
    return "okay";
  } else {
    return null;
  }
}
对交叉点类型和并集进行了简要说明
类型,但似乎没有关于此的进一步参考。

类型可以看作是一组值。例如,如果
Boolean
是值
true
false
的集合,则表示某个值具有类型
Boolean
意味着它是值
true
false

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


您可能知道,并集和交集是集合操作,因此它们也适用于类型。例如,当有类型T1={male,female}和T2={not application}时,可以构建类型T3=T1\union T2={male,female,not application}。这种类型有用的一个例子是对以下问题的回答:“你的第一个孩子的性别是什么?”因为有些人没有孩子,他们可能会回答:不适用。

并集和交集类型只是将类型视为值集(大多数是无限集)。如果这就是你对类型的看法,那么对集合的任何操作都可以应用于类型(值集合),至少在概念上创建一个新的类型(值集合)

联合类型在某些意义上类似于和类型,您似乎很熟悉它。事实上,我经常听到总和类型被描述为“受歧视的联合”类型。基本区别在于(Haskell表示法)
data FooBar=Foo Integer | Bar String
这样的求和类型允许您判断给定的
FooBar
值是包含
整数
还是
字符串
(因为
FooBar
值被标记为
Foo
还是
Bar
)。即使我们在两种类型相同的地方写入
data FooBar=Foo Integer | Bar Integer
,“标记”也会添加额外的信息,我们可以知道
FooBar
值是“哪个整数”

union类型的等效项类似于(无效的Haskell)
data FooBar=Integer | String
FooBar
中的值只是所有字符串值和所有整数值。如果我们将一个并集类型设置为两个相同的类型,比如
data FooBar=Integer | Integer
,那么它在逻辑上应该与
Integer
不可区分,因为集合与自身的并集就是自身

原则上,对于类型U(即类型a和B的并集)中的值,可以做的事情只是对As和Bs起作用的操作;任何只在As或Bs上工作的操作都可能会得到错误的输入类型,因为U没有信息来说明它是a还是B.1

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

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

联合类型在具有子类型的语言中可能很有趣(这在面向对象编程语言中很常见)。如果将一个公共超类型的两个子类型合并在一起,则得到的结果至少支持该超类型的操作,但它排除了该超类型的任何其他子类型,因此这与仅使用该超类型不同

交集类型正是概念,但使用交集而不是并集。这意味着你可以用类型I中的一个值做的事情,它是类型a和B的交集,是对As起作用的操作加上对Bs起作用的操作;I中的任何东西都保证同时是A和B,因此它可以安全地用于任何一种操作

在使用类似Haskell类型系统的语言中,这些也不是很有趣。因为具体类型是不相交的,所以任何非平凡的交集都是空的。但是,类型类约束可以提供类似于交叉点类型的东西;如果将多个类型类约束添加到同一类型变量,则在需要该类型变量的情况下,可以使用的唯一值是所有类型类的“交集”中的类型,并且可以对此类值使用的操作是与任何类型类一起使用的操作


1您可以想象将一个操作
A->C
和一个操作
B->D
组合起来,得到一个操作
(A | B)->(C | D)
,就像您可以使用sum类型的标记将sum类型“路由”到适当的操作一样。但对于完全通用的联合类型来说,它变得模糊了。如果A和B重叠(并且重叠类型在获得union类型后立即进入fray),那么对重叠区域中的值调用哪个操作?如果你能分辨出它是A还是B,那么你真的得到了一个求和类型而不是联合类型,如果你应用了一些任意的解析策略,比如选择
A->C
操作,因为
A
在联合类型的定义中前面列出,然后,在简单的情况下,事情可以正常工作,但如果您有
(
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
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