Typer i formelspråket Power Query M

Power Query M-formelspråket är ett användbart och uttrycksfullt kombinationsspråk för data. Men det har vissa begränsningar. Det finns till exempel ingen stark tillämpning av typsystemet. I vissa fall krävs en mer rigorös validering. Lyckligtvis tillhandahåller M ett inbyggt bibliotek med stöd för typer för att göra en starkare validering möjlig.

Utvecklare bör ha en grundlig förståelse av typsystemet för att kunna göra detta med all generalitet. Och även om Power Query M-språkspecifikationen förklarar typsystemet väl, lämnar det några överraskningar. Validering av funktionsinstanser kräver till exempel ett sätt att jämföra typer för kompatibilitet.

Genom att utforska M-typsystemet mer noggrant kan många av dessa problem klargöras, och utvecklare kommer att få möjlighet att skapa de lösningar de behöver.

Kunskap om predikatkalkyl och naiv uppsättningsteori bör vara tillräcklig för att förstå den notation som används.

FÖRBEREDELSER

(1) B := { true; false }
B är den typiska uppsättningen booleska värden

(2) N := { giltiga M-identifierare }
N är uppsättningen med alla giltiga namn i M. Detta definieras någon annanstans.

(3) P := ⟨B, T
P är uppsättningen med funktionsparametrar. Var och en är möjligen valfri och har en typ. Parameternamn är irrelevanta.

(4) Pn := ⋃0≤i≤ni, Pi⟩
Pn är uppsättningen för alla ordnade sekvenser av n-funktionsparametrar.

(5) P := ⋃0≤i≤∞P i*
P* är uppsättningen av alla möjliga sekvenser av funktionsparametrar, från längd 0 upp.

(6) F := ⟨B, N, T
F är uppsättningen för alla postfält. Varje fält är eventuellt valfritt, har ett namn och en typ.

(7) Fn := ∏0≤i≤n F
Fn är uppsättningen för alla uppsättningar med n postfält.

(8) F := ( ⋃0≤i≤∞Fi ) ∖ { F | ⟨b1, n1, t1⟩, ⟨b2, n2, t2⟩ ∈ Fn1 = n2 }*
F* är uppsättningen för alla uppsättningar (oavsett längd) för postfält, förutom de uppsättningar där fler än ett fält har samma namn.

(9) C := ⟨N,T
C är uppsättningen med kolumntyper för tabeller. Varje kolumn har ett namn och en typ.

(10) Cn ⊂ ⋃0≤i≤ni, C⟩
Cn är uppsättningen för alla ordnade sekvenser av n kolumntyper.

(11) C := ( ⋃0≤i≤∞Ci ) ∖ { Cm | ⟨a, ⟨n1, t1⟩⟩, ⟨b, ⟨n2, t2⟩⟩ ∈ Cmn1 = n2 }*
C* är uppsättningen med alla kombinationer (oavsett längd) för kolumntyper, förutom de där fler än en kolumn har samma namn.

M TYPER

(12) TF := ⟨P, P⟩*
En funktionstyp består av en returtyp och en ordnad lista med noll eller fler funktionsparametrar.

(13) TL :=〖T〗
En listtyp anges av en viss typ (kallas "objekttyp") omsluten i klammerparenteser. Eftersom klammerparenteser används i metallanguage, 〖 〗 hakparenteser används i det här dokumentet.

(14) TR := ⟨B, F⟩*
En posttyp har en flagga som anger om den är "öppen" och noll eller fler osorterade postfält.

(15) TRo := ⟨true, F⟩

(16) TR := ⟨false, F⟩
TRo och TR är notationella genvägar för öppna respektive stängda posttyper.

(17) T T := C *
En tabelltyp är en ordnad sekvens med kolumntyper med noll eller fler, där det inte finns några namnkollisioner.

(18) TP := { any; none; null; logical; number; time; date; datetime; datetimezone; duration; text; binary; type; list; record; table; function; anynonnull }
En primitiv typ är en från den här listan med M-nyckelord.

(19) TN := { tn, u ∈ T | tn = u+null } = nullable t
Alla typer kan dessutom markeras som nullbara med hjälp av nyckelordet "nullable" .

(20) T := TFTLTRT T TPT N
Uppsättningen med alla M-typer är en union av dessa sex uppsättningar av typer:
Funktionstyper, listtyper, posttyper, tabelltyper, primitiva typer och nullbara typer.

FUNKTIONER

En funktion måste definieras: Ej inullerbar : TT
Den här funktionen tar en typ och returnerar en typ som är likvärdig förutom att den inte överensstämmer med null-värdet.

IDENTITETER

Vissa identiteter behövs för att definiera vissa specialfall och kan också hjälpa till att klargöra ovanstående.

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

TYPKOMPATIBILITET

Som definierats någon annanstans kan en M-typ användas med en annan M-typ om och endast om alla värden som överensstämmer med den första typen också överensstämmer med den andra typen.

Här definieras en kompatibilitetsrelation som inte är beroende av överensstämmande värden och som baseras på egenskaperna för själva typerna. Det förväntas att den här relationen, enligt definitionen i det här dokumentet, helt motsvarar den ursprungliga semantiska definitionen.

Relationen "är kompatibel med" : ≤ : BT × T
I avsnittet nedan representerar ett gemener alltid en M-typ, ett element av T.

A Φ representerar en delmängd av F* eller C*.

(28) tt
Den här relationen är reflexiv.

(29) tentbtbtctat c
Den här relationen är transitiv.

(30) Ingen ≤ t ≤ några
M-typer bildar ett gitter över den här relationen. ingen är längst ned, och någon är överst.

(31) ta, tbTNtataNonNullable(ta) ≤ NonNullable(tb)
Om två typer är kompatibla är de icke-inullbara motsvarigheterna också kompatibla.

(32) null ≤ tT N
Den primitiva typen null är kompatibel med alla typer av null-typer.

(33) tTN ≤ anynonnull
Alla icke-inullbara typer är kompatibla med anynonnull.

(34) Ej inullerbara(t) ≤ t
En icke-inullerbar typ är kompatibel med den nullbara motsvarigheten.

(35) tTFt ≤ funktion
Alla funktionstyper är kompatibla med funktionen.

(36) tTLt ≤ lista
Alla listtyper är kompatibla med listan.

(37) tTRt ≤ post
Alla posttyper är kompatibla med posten.

(38) t ∈ T Tt ≤ tabell
Alla tabelltyper är kompatibla med tabellen.

(39) tentb ↔ 〖ta〗≤〖tb〗
En listtyp är compaible med en annan listtyp om objekttyperna är kompatibla och vice versa.

(40) taTF = ⟨ pa, p* ⟩, tbTF = ⟨ pb, p* ⟩ ∧ papbtent b
En funktionstyp är kompatibel med en annan funktionstyp om returtyperna är kompatibla och parameterlistorna är identiska.

(41) tenTRo, tbTRtat b
En öppen posttyp är aldrig kompatibel med en sluten posttyp.

(42) taTR• = ⟨false, Φ⟩, tbTRo = ⟨true, Φ⟩ → tat b
En stängd posttyp är kompatibel med en i övrigt identisk öppen posttyp.

(43) taTRo = ⟨true, (Φ, ⟨true, n, any⟩)⟩, tbTRo = ⟨true, Φ⟩ → tatbtbt a
Ett valfritt fält med typen kan ignoreras när två öppna posttyper jämförs.

(44) taTR = ⟨b, (Φ, ⟨β, n, ua⟩)⟩, tbTR = ⟨b, (Φ, ⟨β, n, ub⟩)⟩ ∧ uaubtat b
Två posttyper som endast skiljer sig åt med ett fält är kompatibla om fältets namn och valfrihet är identiska och typerna av det nämnda fältet är kompatibla.

(45) taTR = ⟨b, (Φ, ⟨false, n, u⟩)⟩, tbTR = ⟨b, (Φ, ⟨true, n, u⟩)⟩ → tat b
En posttyp med ett fält som inte är valfritt är kompatibelt med en posttyp som är identisk men för det fältet är valfritt.

(46) taTRo = ⟨true, (Φ, ⟨b, n, u⟩)⟩, tbTRo = ⟨true, Φ⟩ → tat b
En öppen posttyp är kompatibel med en annan öppen posttyp med ett fält som är färre.

(47) taT T = (Φ, ⟨i, ⟨n, ua⟩⟩), tbT T = (Φ, ⟨i, ⟨n, ub⟩⟩) ∧ uau btat b
En tabelltyp är kompatibel med en andra tabelltyp, som är identisk men för en kolumn som har en annan typ, när typerna för den kolumnen är kompatibla.

REFERENSER

Microsoft Corporation (2015 augusti)
Microsoft Power Query för Formelspråkspecifikation för Excel [PDF]
Hämtad från https://msdn.microsoft.com/library/mt807488.aspx

Microsoft Corporation (n.d.)
Power Query M-funktionsreferens [webbsida]
Hämtad från https://msdn.microsoft.com/library/mt779182.aspx