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

Fra*_*raK 3 f# functional-programming typescript union-types

所以我正在阅读关于联合类型的 Typescript 官方文档,我认为它与 F# 中的“有区别的联合”相同(假设它们具有不同的语法但相同的概念),因为我有 F# 背景并给出了事实两者都得到微软的支持。但是查看文档,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 进行区分,因为该语言没有提供特定的表达式来执行此操作,因此您需要通过所有联合类型都具有的值进行区分,即判别式。这样对吗?

Won*_*Hau 7

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

TypeScript 联合类型 = 未标记联合类型。
F# 区分联合 =标记联合类型。

换句话说,可以在 F# 中建模的每个可区分联合都可以在 Typescript 联合类型中同构建模,但反之则不然。

例如,以下 F# 中的判别联合:

type a' Option = Some of 'a | None 
Run Code Online (Sandbox Code Playgroud)

可以在 Typescript 中同构建模为:

type Option<T> = {tag: 'Some', value: T} | {tag: 'None'}
Run Code Online (Sandbox Code Playgroud)

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

type UserInput = number | string
Run Code Online (Sandbox Code Playgroud)

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

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

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


Lee*_*Lee 6

类型联合中的操作数(A | B)都是类型,而可区分联合中的情况type U = A | B都是该类型的构造函数U,而不是类型本身。type 的值U在运行时标记,以便您可以区分可能的情况。

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

type A? = (A | null)
Run Code Online (Sandbox Code Playgroud)

其中null是值的单例类型null

对于受歧视的工会,它通常表示为

type a' option = Some of 'a | None 
Run Code Online (Sandbox Code Playgroud)

通过这个公式,值

let o: int option option = Some None
Run Code Online (Sandbox Code Playgroud)

不能用联合类型表示,因为(A?)?== (A | null) | null== A | null==A?