差异联合类型和区分的联合打字稿/ F#

时间:2020-05-06 22:18:24

标签: typescript functional-programming f# union-types

因此,我正在阅读Typescript的有关联合类型的官方文档,并且我认为它与F#中的“区分联合”相同(允许使用不同的语法,但是概念相同),因为我具有F#背景并且考虑到两者都得到了Microsoft的支持。但是从文档来看,F#并没有真正区分“工会类型”和“歧视工会”:https://fsharpforfunandprofit.com/posts/discriminated-unions/

但是,Typescript确实区分了这两个概念:

联盟类型:https://www.typescriptlang.org/docs/handbook/advanced-types.html#union-types

歧视联盟:https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions

所以我想知道这些概念本身是否真的有区别,还是仅依赖于某种语言的概念?

到目前为止,我了解的是F#中的联合类型也是区分联合,因为您可以使用匹配表达式和解构来区分联合类型。

但是,您不能使用Typescript进行区分,因为该语言没有提供执行此操作的特定表达式,因此您需要通过一个值来区分所有联合类型都具有的判别式。这是正确的吗?

2 个答案:

答案 0 :(得分:5)

主要区别在于,Typescript Union Type实际上是F#区分Union的超集。

TypeScript联合类型= 未标记联合类型。
F#歧视联盟= 已标记联盟类型。

换句话说,每个可以用F#建模的有区别的联合都可以用Typescript联合类型同构地建模,但是反之则不成立。

例如,以下F#中的已区分联合:

type a' Option = Some of 'a | None 

可以在Typescript中同构地建模为:

type Option<T> = {tag: 'Some', value: T} | {tag: 'None'}

但是,以下Typescript联合类型不能在F#中同构建模:

type UserInput = number | string

这里的主要区别是TypeScript联合类型不需要标记,但是F#联合类型必须被标记。

因此,我们可以看到TypeScript实际上比F#更灵活,但这并不是没有代价的,未标记的联合实际上是有漏洞的,这意味着在某些类型联合中TypeScript将无法进行类型检查。

这就像未类型的lambda演算是类型化的lambda演算的超集,但是类型lambda演算更容易证明正确。

答案 1 :(得分:2)

类型并集(A | B)中的操作数都是两种类型,而有区别的并集type U = A | B中的个案都是类型U的构造函数,它们本身不是类型。类型U的值在运行时被标记,因此您可以区分可能的情况。

一个结果是,可以以联合类型可能不会嵌套的方式嵌套已区分的联合。联合类型系统中某些类型A的可选值可能表示为

type A? = (A | null)

其中nullnull值的单例类型。

对于有区别的联合,通常表示为

type a' option = Some of 'a | None 

使用此公式表示的值

let o: int option option = Some None

由于(A?)? == (A | null) | null == A | null == A?

,因此无法用联合类型表示