Typer i formelspråket Power Query M

Det 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 för 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 av 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 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 med alla ordnade sekvenser av n-funktionsparametrar.

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

(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≤nF
Fn är uppsättningen med alla uppsättningar av n postfält.

(8) F* := ( ⋃0≤i≤∞Fi ) ∖ { F | ⟨b1, n1, t1⟩, ⟨b2, n2, t2⟩ ∈ Fn1 = n2 }
F* är uppsättningen med 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 med 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 används 〖 〗 hakparenteser 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 noll- eller fler kolumntyper, 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 avnyckelordet "nullable".

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

FUNKTIONER

En funktion måste definieras: NonNullable : 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örutses 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 i T.

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

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

(29) tentbtbtctatc
Den här relationen är transitiv.

(30) Ingen ≤ inte ≤ 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-ullerbara motsvarigheterna också kompatibla.

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

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

(34) NonNullable(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) tTTt ≤ 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* ⟩ ∧ papbtatb
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 typ av stängd post.

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

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

(44) taTR = ⟨b, (Φ, ⟨β, n, ua⟩)⟩, tbTR = ⟨b, (Φ, ⟨β, n, ub⟩)⟩ ∧ uaubtatb
Två posttyper som bara skiljer sig åt med ett fält är kompatibla om fältets namn och valfritt är identiska och fälttyperna är kompatibla.

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

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

(47) taTT = (Φ, ⟨i, ⟨n, ua⟩⟩), tbTT = (Φ, ⟨i, ⟨n, ub⟩⟩) ∧ uaubtatb
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.

REFERENSLISTA

Microsoft Corporation (2015 augusti)
Microsoft Power Query for Excel Formula Language Specification [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