Power Query M 公式语言中的类型

Power Query M 公式语言是一种很有用且富有表现力的数据混合语言。 但它确实有一些局限性。 例如,没有对类型系统的强有力的执行。 在某些情况下,需要进行更严格的验证。 幸运的是,M 提供了一个内置库来支持类型,从而使更强的验证成为可能。

开发人员应对类型系统有一个全面的了解,以便通过任何通用性来实现此目的。 而且,虽然 Power Query M 语言规范对类型系统进行了说明,但也确实留下了一些惊喜。 例如,验证函数实例需要一种比较类型兼容性的方法。

通过更仔细地研究 M 类型系统,可以阐明其中的许多问题,并授权开发人员创建他们需要的解决方案。

谓词演算和朴素集理论的知识应足以理解所使用的表示法。

预备知识

(1) B := { true; false }
B 是典型的布尔值集

(2) N := { 有效的 M 标识符 }
N 是 M 中所有有效名称的集合。此定义来源于别处。

(3) P := ⟨B,T
P 是函数参数的集合。 每个选项都可能是可选的,且具有一个类型。 参数名不相关。

(4) Pn := ⋃0≤i≤n ⟨i, Pi
Pn 是 n 个函数参数的所有序序列的集合。

(5) P := ⋃*P i
P* 是所有可能的函数参数序列的集合,从长度 0 开始。

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

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

(8) F := (⋃* Fi) ∖ { F | ⟨b 1, n 1, t1⟩, ⟨b2n 2t2⟩ ∈ Fn 1n =
F* 是所有记录字段集(任何长度)的集合,但多个字段具有相同名称的集合除外。

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

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

(11) C := (⋃*Ci) ∖ { Cm | ⟨a, ⟨n 1, t1⟩⟩, ⟨b, ⟨n2t2⟩⟩ ∈ Cm ⋀ =
C* 是列类型的所有组合(任意长度)的集合,但不包括多个列具有相同名称的组合。

M 类型

(12) TF := ⟨P,P*
函数类型由返回类型和由零或多个函数参数组成的有序列表组成。

(13) TL :=+T}
列表类型由用大括号括起来的给定类型(称为“项目类型”)表示。 由于元语言中使用了大括号, 〖 〗 本文档使用括号。

(14) TR := ⟨B,F*
记录类型有一个标志(指示是否为 open 类型),以及零个或多个无序的记录字段。

(15) TRo := ⟨trueF

(16) TR := ⟨falseF
TRo 和 TR 分别指 open 和 closed 记录类型的表示法快捷方式。

(17) T := 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 | t n = u+null } = 可为 null t
通过使用“nullable”关键字,任何类型都可以标记为 nullable 。

(20) T := TF ∪ TL ∪ TR ∪ TT ∪ TP ∪ TN
所有 M 类型的集合是这六组类型的并集:
函数类型、列表类型、记录类型、表类型、基元类型和可空类型

FUNCTIONS

需要定义一个函数:NonNullable : TT
此函数接受一个类型,并返回一个等效类型,但它不符合 null 值。

标识

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

(21) 可为 null 的任何 = 任何
(22) 可为 null 的 anynonnull = any
(23) 可以为 null 的 null = null
(24) 可为 null 无 = null
(25) 可为 null 的可为 null tT = 可为 null t
(26) NonNullable(可为 null tT) = NonNullable(t
(27) NonNullable(any) = anynonnull

类型兼容性

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

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

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

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

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

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

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

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

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

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

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

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

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

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

(38) tT Tt ≤ 表
所有表类型都与表兼容。

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

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

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

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

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

(44) ta ∈TR = ⟨b, (Л, ⟨βnua⟩) ⟩, tbTR = ⟨b, (⟨βn, u b⟩) ⟩ ∧ u a ≤ ubtatb
如果字段的名称和可选性相同,且所述字段的类型是兼容的,则仅相差一个字段的两个记录类型是兼容的。

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

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

(47) ta ∈T T = (Ο, ⟨i, ⟨nua⟩⟩), tbT T = (, ⟨i, ⟨nub⟩⟩) ∧ uaubtat b
第一种表类型与第二种表类型兼容,但对于具有不同类型的一列,如果该列的类型兼容,则这两种表类型相同。