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≤∞Pi
P* 是所有可能的函数参数序列的集合,从长度 0 开始。

(6) F := ⟨B, N, T
F 是所有记录字段的集合。 每个字段可能是可选的,具有一个名称和类型。

(7) Fn := ∏0≤i≤nF
Fn 是 n 个记录字段的所有集合。

(8) F* := ( ⋃0≤i≤∞Fi ) ∖ { F | ⟨b1, n1, t1⟩, ⟨b2, n2, t2⟩ ∈ F ⋀ n1 = n2 }
F* 是所有记录字段集(任何长度)的集合,但多个字段具有相同名称的集合除外。

(9) C := ⟨N,T
C 是表的一组列类型。 每个列都具有一个名称和类型。

(10) Cn ⊂ ⋃0≤i≤n ⟨i, C⟩
Cn 是 n 列类型的所有有序序列的集合。

(11) C* := ( ⋃0≤i≤∞Ci ) ∖ { Cm | ⟨a, ⟨n1, t1⟩⟩, ⟨b, ⟨n2, t2⟩⟩ ∈ Cm ⋀ n1 = 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 : TT
此函数接受一个类型,并返回一个等效类型,但它不符合 null 值。

标识

需要一些标识来定义一些特殊的情况,这也有助于阐明上述内容。

(21) nullable any = any
(22) nullable anynonnull = any
(23) nullable null = null
(24) nullable none = null
(25) nullable nullable tT = nullable t
(26) NonNullable(nullable tT) = NonNullable(t)
(27) NonNullable(any) = anynonnull

类型兼容性

如其他地方所定义的,当且仅当符合第一个类型的所有值也符合第二个类型时,M 类型才可与另一个 M 类型兼容。

此处定义了一个不依赖于符合值的兼容关系,且它基于类型本身的属性。 值得注意的是,本文档中定义的这种关系完全等同于最初的语义定义。

“兼容”关系:≤ : BT × T
在下面的部分中,小写的 t 将始终表示 M 类型,即 T 的一个元素 。

Φ 将代表 F*C* 的子集。

(28) tt
此关系为自反关系。

(29) tatbtbtctatc
此关系为可传递关系。

(30) none ≤ t ≤ any
M 类型在这个关系上形成一个点阵;没有一个是底部,任何一个都是顶部 。

(31) ta, tbTNtataNonNullable(ta) ≤ NonNullable(tb)
如果两种类型是兼容的,那么 NonNullable 的等效项也是兼容的。

(32) null ≤ tTN
基元类型 null 与所有可为 null 的类型兼容 。

(33) tTN ≤ anynonnull
所有不可为 null 的类型都与 anynonnull 兼容。

(34) NonNullable(t) ≤ t
NonNullible 类型与可为 null 的等效类型兼容。

(35) tTFt ≤ function
所有函数类型都与函数兼容。

(36) tTLt ≤ list
所有列表类型都与列表兼容。

(37) tTRt ≤ record
所有记录类型都与记录兼容。

(38) tTTt ≤ table
所有表类型都与表兼容。

(39) tatb ↔ 〖ta〗≤〖tb
如果项类型兼容,则列表类型可以与其他列表类型兼容,反之亦然。

(40) taTF = ⟨ pa, p* ⟩, tbTF = ⟨ pb, p* ⟩ ∧ papbtatb
如果返回类型兼容,且参数列表相同,则函数类型与另一种函数类型兼容。

(41) taTRo, tbTRtatb
open 记录类型永远与 closed 记录类型不兼容。

(42) taTR = ⟨false, Φ⟩, tbTRo = ⟨true, Φ⟩ → tatb
closed 记录类型与其他相同的 open 记录类型兼容。

(43) taTRo = ⟨true, (Φ, ⟨true, n, any⟩)⟩, tbTRo = ⟨true, Φ⟩ → tatbtbta
在比较两个 open 记录类型时,任何类型的可选字段都可能被忽略 。

(44) taTR = ⟨b, (Φ, ⟨β, n, ua⟩)⟩, tbTR = ⟨b, (Φ, ⟨β, n, ub⟩)⟩ ∧ uaubtatb
如果字段的名称和可选性相同,且所述字段的类型是兼容的,则仅相差一个字段的两个记录类型是兼容的。

(45) taTR = ⟨b, (Φ, ⟨false, n, u⟩)⟩, tbTR = ⟨b, (Φ, ⟨true, n, u⟩)⟩ → tatb
带有非可选字段的记录类型与相同的记录类型兼容,但该字段是可选的。

(46) taTRo = ⟨true, (Φ, ⟨b, n, u⟩)⟩, tbTRo = ⟨true, Φ⟩ → tatb
open 记录类型与另一个少一个字段的 open 记录类型兼容。

(47) taTT = (Φ, ⟨i, ⟨n, ua⟩⟩), tbTT = (Φ, ⟨i, ⟨n, ub⟩⟩) ∧ uaubtatb
第一种表类型与第二种表类型兼容,但对于具有不同类型的一列,如果该列的类型兼容,则这两种表类型相同。

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