Power Query M 公式语言中的类型
Power Query M 公式语言是一种很有用且富有表现力的数据混合语言。 但它确实有一些局限性。 例如,没有对类型系统的强有力的执行。 在某些情况下,需要进行更严格的验证。 幸运的是,M 提供了一个内置库来支持类型,从而使更强的验证成为可能。
开发人员应对类型系统有一个全面的了解,以便通过任何通用性来实现此目的。 而且,虽然 Power Query M 语言规范对类型系统进行了说明,但也确实留下了一些惊喜。 例如,验证函数实例需要一种比较类型兼容性的方法。
通过更仔细地研究 M 类型系统,可以阐明其中的许多问题,并授权开发人员创建他们需要的解决方案。
谓词演算和朴素集理论的知识应足以理解所使用的表示法。
预备知识
(1) B := { true; false }
B 是典型的布尔值集
(2) N := { valid M identifiers }
N 是 M 中所有有效名称的集合。此定义来源于别处。
(3) P := ⟨B, T⟩
P 是函数参数的集合。 每个选项都可能是可选的,且具有一个类型。 参数名不相关。
(4) Pn := ⋃0≤i≤n ⟨i, Pi⟩
Pn 是 n 个函数参数的所有序序列的集合。
(5) P := ⋃0≤i≤∞P i*
P* 是所有可能的函数参数序列的集合,从长度 0 开始。
(6) F := ⟨B, N, T⟩
F 是所有记录字段的集合。 每个字段可能是可选的,具有一个名称和类型。
(7) Fn := ∏0≤i≤n F
Fn 是 n 个记录字段的所有集合。
(8) F := (⋃0≤i≤∞ Fi) ∖ { F | ⟨b 1, n 1, t1⟩, ⟨b2, n 2, t2⟩ ∈ F ⋀ n 1 = n2 }*
F* 是所有记录字段集(任何长度)的集合,但多个字段具有相同名称的集合除外。
(9) C := ⟨N,T⟩
C 是表的一组列类型。 每个列都具有一个名称和类型。
(10) Cn ⊂ ⋃0≤i≤n ⟨i, C⟩
Cn 是 n 列类型的所有有序序列的集合。
(11) C := (⋃0≤i≤∞ Ci) ∖ { Cm | ⟨a, ⟨n 1, t1⟩⟩, ⟨b, ⟨n2, t2⟩⟩ ∈ Cm ⋀ n 1 = n2 }*
C* 是列类型的所有组合(任意长度)的集合,但不包括多个列具有相同名称的组合。
M 类型
(12) TF := ⟨P, P*⟩
函数类型由返回类型和由零或多个函数参数组成的有序列表组成。
(13) TL :=〖T〗
列表类型由用大括号括起来的给定类型(称为“项目类型”)表示。
由于元语言中使用了大括号, 〖 〗 本文档使用括号。
(14) TR := ⟨B, F*⟩
记录类型有一个标志(指示是否为 open 类型),以及零个或多个无序的记录字段。
(15) TRo := ⟨true, F⟩
(16) TR• := ⟨false, F⟩
TRo 和 TR• 分别指 open 和 closed 记录类型的表示法快捷方式。
(17) TT := C*
表类型是零或多个列类型的有序序列,其中不存在名称冲突。
(18) TP := { any; none; null; logical; number; time; date; datetime; datetimezone; duration; text; binary; type; list; record; table; function; anynonnull }
基元类型是 M 关键字列表中的一个。
(19) TN := { tn, u ∈ T | tn = u+null } = nullable t
通过使用“nullable”关键字,任何类型都可以标记为 nullable 。
(20) T := TF ∪ TL ∪ TR ∪ TT ∪ TP ∪ TN
所有 M 类型的集合是这六组类型的并集:
函数类型、列表类型、记录类型、表类型、基元类型和可空类型。
FUNCTIONS
需要定义一个函数:NonNullable : T ← T
此函数接受一个类型,并返回一个等效类型,但它不符合 null 值。
标识
需要一些标识来定义一些特殊的情况,这也有助于阐明上述内容。
(21) nullable any = any
(22) nullable anynonnull = any
(23) nullable null = null
(24) nullable none = null
(25) nullable nullable t ∈ T = nullable t
(26) NonNullable(nullable t ∈ T) = NonNullable(t)
(27) NonNullable(any) = anynonnull
类型兼容性
如其他地方所定义的,当且仅当符合第一个类型的所有值也符合第二个类型时,M 类型才可与另一个 M 类型兼容。
此处定义了一个不依赖于符合值的兼容关系,且它基于类型本身的属性。 值得注意的是,本文档中定义的这种关系完全等同于最初的语义定义。
“兼容”关系:≤ : B ← T × T
在下面的部分中,小写的 t 将始终表示 M 类型,即 T 的一个元素 。
Φ 将代表 F* 或 C* 的子集。
(28) t ≤ t
此关系为自反关系。
(29) ta ≤ tb ∧ tb ≤ tc → ta ≤ tc
此关系为可传递关系。
(30) none ≤ t ≤ any
M 类型在这个关系上形成一个点阵;没有一个是底部,任何一个都是顶部 。
(31) ta, tb ∈ TN ∧ ta ≤ ta → NonNullable(ta) ≤ NonNullable(tb)
如果两种类型是兼容的,那么 NonNullable 的等效项也是兼容的。
(32) null ≤ t ∈ TN
基元类型 null 与所有可为 null 的类型兼容 。
(33) t ∉ TN ≤ anynonnull
所有不可为 null 的类型都与 anynonnull 兼容。
(34) NonNullable(t) ≤ t
NonNullible 类型与可为 null 的等效类型兼容。
(35) t ∈ TF → t ≤ function
所有函数类型都与函数兼容。
(36) t ∈ TL → t ≤ list
所有列表类型都与列表兼容。
(37) t ∈ TR → t ≤ record
所有记录类型都与记录兼容。
(38) t ∈ TT → t ≤ table
所有表类型都与表兼容。
(39) ta ≤ tb ↔ 〖ta〗≤〖tb〗
如果项类型兼容,则列表类型可以与其他列表类型兼容,反之亦然。
(40) ta ∈ TF = ⟨ pa, p* ⟩, tb ∈ TF = ⟨ pb, p* ⟩ ∧ pa ≤ pb → ta ≤ tb
如果返回类型兼容,且参数列表相同,则函数类型与另一种函数类型兼容。
(41) ta ∈ TRo, tb ∈ TR• → ta ≰ tb
open 记录类型永远与 closed 记录类型不兼容。
(42) ta ∈ TR• = ⟨false, Φ⟩, tb ∈ TRo = ⟨true, Φ⟩ → ta ≤ tb
closed 记录类型与其他相同的 open 记录类型兼容。
(43) ta ∈ TRo = ⟨true, (Φ, ⟨true, n, any⟩)⟩, tb ∈ TRo = ⟨true, Φ⟩ → ta ≤ tb ∧ tb ≤ ta
在比较两个 open 记录类型时,任何类型的可选字段都可能被忽略 。
(44) ta ∈ TR = ⟨b, (Φ, ⟨β, n, ua⟩)⟩, tb ∈ TR = ⟨b, (Φ, ⟨β, n, ub⟩)⟩ ∧ ua ≤ ub → ta ≤ tb
如果字段的名称和可选性相同,且所述字段的类型是兼容的,则仅相差一个字段的两个记录类型是兼容的。
(45) ta ∈ TR = ⟨b, (Φ, ⟨false, n, u⟩)⟩, tb ∈ TR = ⟨b, (Φ, ⟨true, n, u⟩)⟩ → ta ≤ tb
带有非可选字段的记录类型与相同的记录类型兼容,但该字段是可选的。
(46) ta ∈ TRo = ⟨true, (Φ, ⟨b, n, u⟩)⟩, tb ∈ TRo = ⟨true, Φ⟩ → ta ≤ tb
open 记录类型与另一个少一个字段的 open 记录类型兼容。
(47) ta ∈ TT = (Φ, ⟨i, ⟨n, ua⟩⟩), tb ∈ TT = (Φ, ⟨i, ⟨n, ub⟩⟩) ∧ ua ≤ ub → ta ≤ tb
第一种表类型与第二种表类型兼容,但对于具有不同类型的一列,如果该列的类型兼容,则这两种表类型相同。
REFERENCES
Microsoft Corporation(2015 年 8 月)
Microsoft Power Query for Excel 公式语言规范 [PDF]
检索自 https://msdn.microsoft.com/library/mt807488.aspx
Microsoft Corporation (n.d.)
Power Query M 函数参考 [网页]
检索自 https://msdn.microsoft.com/library/mt779182.aspx