1. 积类型
在类型理论中,类型的积(product)是一个复合类型(compounded type),
积运算的操作数是类型(type),并且与操作数的顺序有关,
类型 A 和类型 B 的积类型,通常记为 A × B 。
一个具有积类型的表达式,通常被称为元组(tuple),
积类型有时也被称为元组类型。
以下为Haskell中的元组示例,
-- Haskell Code
(True, 1) :: Num t => (Bool, t)
("Hello world", False) :: ([Char], Bool)
(4, 5, "Six", True, 'b') :: (Num t1, Num t2) => (t1, t2, [Char], Bool, Char)
2. 和类型
和类型(sum type),又称为标签联合(tagged union),也是一种复合类型,
可看做是把不同的类型,通过携带标签(tag field)的方式的放在了一起。
类型 A 和类型 B 的和类型,通常记为 A + B 。
-- Haskell Code
data Bool = False | True
data Maybe a = Just a | Nothing
其中,值构造器就可以看做标签(tag field)。
处理和类型的值,可以使用模式匹配,
-- Haskell Code
f :: Maybe Int -> Int
f x = case x of
Just i -> i
Nothing -> 0
3. 联合类型
联合类型(union type)的值,是类型值集的并集。
例如,在C语言中,signed char
的取值范围是-128 ~ 127
,
unsigned char
取值范围是0 ~ 255
,
则这两个类型的联合类型,取值范围就是-128 ~ 255
。
C语言中的联合类型不是类型安全的(not typesafe),
因为任何一个类型中的操作(operation),都可以用于联合类型,
这样如果当前值不属于那个类型时,就会出错。
下面我们来看TypeScript中的联合类型,它的类型安全的(typesafe),
TypeScript中的联合类型记为,A | B。
// TypeScript Code
interface Bird {
fly();
layEggs();
}
interface Fish {
swim();
layEggs();
}
function getSmallPet(): Fish | Bird {
// ...
}
let pet = getSmallPet();
pet.layEggs(); // okay
pet.swim(); // errors
以上TypeScript代码中,getSmallPet
返回值的类型是一个联合类型Fish | Bird
,
则表明,或者类型为Fish
,或者类型为Bird
。
TypeScript只允许调用Fish
和Bird
都有的方法,例如,layEggs
,
这样做是类型安全的。
4. 交叉类型
交叉类型(intersection type)的值,是类型值集的交集。
例如,在C语言中,signed char
的取值范围是-128 ~ 127
,
而unsigned char
取值范围是0 ~ 255
,
则它们的交叉类型,取值范围是0 ~ 127
。
对于交叉类型的值,可以安全的进行每个类型上可以进行的操作,
因为它属于所有的类型。
Flow.js中的交叉类型记为,A & B。
// @flow
type A = { a: number };
type B = { b: boolean };
type C = { c: string };
function method(value: A & B & C) {
// ...
}
// $ExpectError
method({ a: 1 }); // Error!
// $ExpectError
method({ a: 1, b: true }); // Error!
method({ a: 1, b: true, c: 'three' }); // Works!
注:
(1)对联合类型来说,值集是参与联合的类型的值集之并,
但值集上类型安全的操作是交集。
对于交叉类型来说,值集是参与交叉的类型的值集之交,
但是值集上类型安全的操作是并集。
从值集的角度进行说明,其实不够严谨,应该从类型推导规则的角度来看。
这里只是不严谨的理解一下。
(2)交叉类型和联合类型是对偶概念(dual)。
例如,交叉类型经常用于描述重载函数(overloaded function)的类型,
/* @flow */
class Foo {}
class Bar {}
declare var f: ((x: Foo) => void) & ((x: Bar) => void);
f(new Foo());
f(true); // Flow will error here.
TypeScript有两种方式来描述,
interface A {
(t: number): void;
(t: string): void;
}
var func: A
// in TypeScript 1.4
interface A {
(t: number | string): void;
}
var func: A
这两种描述是等价的,
(t: number | string): void
(t: number) => void & (t: string) => void
TypeScript 1.6已增加了交叉类型。
参考
Union types
Union type
TypeScript: union types
Intersection types
Thoughts on Intersection Types
Flow: intersection types
Null-tracking, or the difference between union and sum types
网友评论