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≤ni, 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⟩ ∈ Fn1 = n2 }
F* 是記錄欄位所有集合 (任何長度) 的集合,但其中有超過一個欄位名稱相同的集合除外。

(9) C := ⟨N,T
C 是資料表的資料行類型集合。 每個資料行各有名稱和類型。

(10) Cn ⊂ ⋃0≤i≤ni, C
Cn 是 n 資料行類型的所有排序序列集合。

(11) C* := ( ⋃0≤i≤∞Ci ) ∖ { Cm | ⟨a, ⟨n1, t1⟩⟩, ⟨b, ⟨n2, t2⟩⟩ ∈ Cmn1 = n2 }
C* 是資料行類型所有組合 (任何長度) 的集合,但其中超過一個資料行名稱相同的除外。

M 類型

(12) TF := ⟨P, P*
函式類型包含傳回型別,以及零或多個函式參數的排序清單。

(13) TL :=〖T
清單類型以大括號括住的特定類型 (稱為「項目類型」) 來表示。 由於元語言中使用了大括號, 因此在本文件中會使用〖 〗 括弧。

(14) TR := ⟨B, F*
記錄類型有一個會指出其是否為「已開啟」的旗標,以及零或多個未排序的記錄欄位。

(15) TRo := ⟨true, F

(16) TR := ⟨false, F
TRo and TR 分別是已開啟和已關閉記錄類型的標記捷徑。

(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" 關鍵字來另外標記為可為 Null。

(20) T := TFTLTRTTTPTN
所有 M 類型集合都是這六種類型集合的聯合:
函式類型、清單類型、記錄類型、資料表類型、基本類型及可為 Null 的類型。

函式

有一個必須定義的函式: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 的元素。

A Φ 將代表 F*C* 的子集。

(28) tt
This relation is reflexive.

(29) tatbtbtctatc
This relation is transitive.

(30) none ≤ t ≤ any
M 類型會透過此關聯性來形成辨識格;none 是底部,而 any 是頂端。

(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 ≤ 函式
所有函式類型都與函式相容。

(36) tTLt ≤ 清單
所有清單類型都與清單相容。

(37) tTRt ≤ 記錄
所有記錄類型都與記錄相容。

(38) tTTt ≤ 資料表
所有資料表類型都與資料表相容。

(39) tatb ↔ 〖ta〗≤〖tb
如果項目類型相容,則清單類型會與另一個清單類型相容,反之亦然。

(40) taTF = ⟨ pa, p* ⟩, tbTF = ⟨ pb, p* ⟩ ∧ papbtatb
如果傳回型別相容,且參數清單相同,則函式類型會與另一個函式類型相容。

(41) taTRo, tbTRtatb
已開啟記錄類型一律不會與已關閉記錄類型相容。

(42) taTR = ⟨false, Φ⟩, tbTRo = ⟨true, Φ⟩ → tatb
已關閉記錄類型與另一個相同的已開啟記錄類型相容。

(43) taTRo = ⟨true, (Φ, ⟨true, n, any⟩)⟩, tbTRo = ⟨true, Φ⟩ → tatbtbta
在比較兩個已開啟記錄類型時,可能會忽略具有 any 類型的選擇性欄位。

(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
已開啟記錄類型與另一個具有較少欄位的已開啟記錄類型相容。

(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