Standard ML

Den aktuella versionen av sidan har ännu inte granskats av erfarna bidragsgivare och kan skilja sig väsentligt från versionen som granskades den 27 februari 2022; kontroller kräver 3 redigeringar .
Standard ML
Semantik Formell , tolkningsorienterad
Språkklass applikativ ,
funktionell ,
imperativ
Utförandetyp generell mening
Framträdde i 1984 [1] , 1990 [2] , 1997 [3]
Författare Robin Milner med flera
Filtillägg _ .sml
Släpp Standard ML '97 (1997 ) ( 1997 )
Typ system Hindley - Milner
Stora implementeringar många
Dialekter Alice , SML# , Manticore och andra
Blivit påverkad Lisp , ISWIM , ML , POP-2 , Hope , Clear [4]
påverkas Erlang , Ocaml , Haskell ,
efterträdare ML (sML)
Licens öppen källa
Hemsida sml-family.org
Plattform x86 , AMD64 , PowerPC , ARM , SPARC , S390 , DEC Alpha , MIPS , HPPA , PDP-11 ,
JVM , .Net , LLVM , C-- ,
TAL , C [5] , Ada [6]
OS * BSD , Linux ( Debian , Fedora , etc.) ,
Windows , Cygwin , MinGW ,
Darwin , Solaris ,
Hurd , AIX , HP-UX

Standard ML ( SML är ett allmäntkompilerat programmeringsspråk av högre ordning baserat på systemet av typen Hindley-Milner .

Det kännetecknas av en matematiskt exakt definition (som garanterar identiteten för programmens betydelse oavsett kompilator och hårdvara), som har en bevisad tillförlitlighet av statisk och dynamisk semantik. Det är ett "mest funktionellt " språk [7] [8] , det vill säga det stöder de flesta av de tekniska funktionerna i funktionella språk, men ger också avancerade imperativa programmeringsmöjligheter när det behövs. Kombinerar stabilitet hos program, flexibilitet på nivån av dynamiskt typade språk och hastighet på nivån för C- språk ; ger utmärkt stöd för både snabb prototypframställning och modularitet och storskalig programmering [9] [10] .

SML var det första fristående kompilerade språket i ML- familjen och fungerar fortfarande som ankarspråket i ML -utvecklingsgemenskapen ( efterföljaren ML ) [11] . SML var först med att implementera ett unikt applicerande modulsystem  , ML-modulspråket .

Allmän information

Språket är ursprungligen fokuserat på storskalig programmering av mjukvarusystem: det tillhandahåller effektiva medel för abstraktion och modularitet , vilket ger en hög kodåteranvändningshastighet , och detta gör det också lämpligt för snabb prototypframställning av program, inklusive storskalig . Till exempel, under utvecklingen av den (då fortfarande experimentella) SML/NJ-kompilatorn ( 60 tusen rader per SML), var det ibland nödvändigt att göra radikala förändringar i implementeringen av nyckeldatastrukturer som påverkar dussintals moduler – och den nya versionen av kompilatorn blev klar under dagen. [9] (Se även ICFP Programming Contest 2008, 2009.) Men till skillnad från många andra språk som är lämpliga för snabb prototyping kan SML kompilera mycket effektivt .

SML är känt för sin relativt låga starttröskel och fungerar som undervisningsspråk i programmering vid många universitet runt om i världen [12] . Det är omfattande dokumenterat i arbetsform och används aktivt av forskare som grund för att forska i nya delar av programmeringsspråk och idiom (se till exempel polymorfism av strukturella typer ). Vid det här laget har alla implementeringar av språket (inklusive föråldrade sådana) blivit öppen källkod och gratis .

Utmärkande egenskaper

Språket har en matematiskt exakt ( eng.  rigorous ) formell definition som kallas "Definition" ( eng. The Definition ). För definitionen byggs ett fullständigt säkerhetsbevis som garanterar stabiliteten hos programmen och förutsägbart beteende även med felaktiga indata och eventuella programmeringsfel. Även ett buggigt SML-program beter sig alltid som ett ML-program: det kan gå in i beräkningar för alltid eller skapa ett undantag , men det kan inte krascha [13] .  

SML är ett mestadels funktionellt ( mestadels funktionellt eller primärt funktionellt ) språk [7] [8] , det vill säga det stöder de flesta av de tekniska egenskaperna hos funktionella språk, men ger också imperativa programmeringsmöjligheter . Det kallas oftare för ett " språk av högre ordning för att betona stöd för förstklassiga funktioner samtidigt som det skiljer det från referenstransparenta språk .

SML ger enastående stöd för storskalig programmering genom det mest kraftfulla och uttrycksfulla modulsystemet som är känt ( ML Module Language ). SML implementerar en tidig version av modulspråket, som är ett separat lager av språket: moduler kan innehålla kärnspråksobjekt, men inte vice versa [14] .

Till skillnad från många andra språk i ML- familjen ( OCaml , Haskell , F# , Felix, Opa, Nemerle och andra) är SML väldigt minimalistisk: den har inte inbyggd objektorienterad programmering , samtidighet , ad-hoc polymorfism , dynamisk typning , listgeneratorer och många andra funktioner. SML är dock ortogonal [15] (det vill säga implementerar det minsta nödvändiga, men hela uppsättningen av maximalt olika element), vilket gör det relativt enkelt att emulera andra funktioner, och de tekniker som krävs för detta täcks brett i litteraturen . Faktum är att SML låter dig använda godtyckligt högnivåfunktionalitet som en primitiv för att implementera funktionalitet på ännu högre nivå [16] . I synnerhet byggs implementeringsmodeller av typklasser och monader med endast standard SML-konstruktioner, såväl som objektorienterade programmeringsverktyg [17] . Dessutom är SML ett av få språk som direkt implementerar förstklassiga fortsättningar .

Funktioner

Kraftfullt uttrycksfullt typsystem

Systemet av typen Hindley-Milner (X-M) är en utmärkande egenskap hos ML och dess ättlingar. Det säkerställer tillförlitligheten hos program på grund av tidig upptäckt av fel, hög kodåteranvändning , hög potential för optimering , kombinerar dessa kvaliteter med kortfattadhet och uttrycksfullhet på nivån för dynamiskt typade språk. De mest framträdande egenskaperna som är inneboende i X-M är typpolymorfism , såväl som algebraiska datatyper och mönstermatchning på dem.

Implementeringen av X-M i SML har följande funktioner:

Stöd för funktionell programmering Stöd för imperativ programmering Säkerställer hög programeffektivitet

Användning

Till skillnad från många språk erbjuder SML en mängd olika sätt att använda det [21] :

Samtidigt, i vissa lägen, är en mängd olika målplattformar och kompileringsstrategier möjliga :

Sammanställningsstrategierna skiljer sig också avsevärt:

Språk

Grundläggande semantik

Deklarationer, uttryck, block, funktioner Primitiva typer Sammansatta och definierade typer Föränderliga värden Begränsning av värden

Värdebegränsning _ _  _ _

Kontrollstrukturer

Storskalig programmering

Modularitet

SML -modulsystemet är det mest utvecklade modulsystemet inom programmeringsspråk. Den upprepar semantiken för kärn-ML ( eng.  Core ML ), så att beroenden mellan stora programkomponenter byggs som beroenden på en liten nivå. Detta system av moduler består av tre typer av moduler:

  • strukturer ( structure)
  • signaturer ( signature)
  • funktioner ( functor)

Strukturer liknar moduler i de flesta programmeringsspråk. Signaturer fungerar som strukturgränssnitt, men är inte strikt knutna till vissa strukturer, utan bygger relationer enligt " många-till-många " -schemat , vilket gör att du flexibelt kan kontrollera synligheten av strukturkomponenter beroende på programkontextens behov.

Funktioner är " funktioner över strukturer ", som låter dig bryta kompileringstidsberoenden och beskriva parametriserade moduler. De gör det möjligt att skriva -säkert beskriva beräkningar på programkomponenter som på andra språk endast kan implementeras genom metaprogrammering [23]  - som C++-mallar , endast utan smärta och lidande [24] , eller makrospråket Lisp , endast med statisk säkerhetskontroll av den genererade koden [23] . De flesta språk har inget som kan jämföras med funktioner alls [25] .

Den grundläggande skillnaden mellan ML-modulspråket är att resultatet av en funktor inte bara kan innehålla värden utan också typer, och de kan bero på de typer som är en del av funktorparametern. Detta gör ML-moduler närmast i sin uttrycksfullhet till system med beroende typer , men till skillnad från de senare kan ML-moduler reduceras till ett platt System F ω (se Modulspråk ML#F-Rossberg-Rousseau-Dreyer ).

Syntax och syntaktisk socker

Språkets syntax är mycket kort, sett till antalet reserverade ord upptar det en mellanposition mellan Haskell och Pascal [26] .

SML har en kontextfri grammatik , även om vissa oklarheter noteras i den. SML/NJ använder LALR(1) , men LALR(2) finns på ett ställe.

Lista över språksökord ( identifierare som matchar dem är inte tillåtna) [27] :

abstype och och även som fall datatyp gör annat slut eqtype undantag fn fun functor handle if in include infix infixr låt lokal nonfix av op öppen eller höj rec delning signatur struct struktur skriv sedan val where while with withtype

Teckenidentifierare är också tillåtna – det vill säga typ-, data- och funktionsnamn kan bestå av följande icke-alfabetiska tecken:

! % & $ # + - * / : < = > ? @ \ ~ ' ^ |

Namnen på dessa symboler kan ha vilken längd som helst [27] :

val ----> = 5 kul !!? ©**??!! x = x - 1 infix 5 $^$^$^$ kul a $^$^$^$ b = a + b val :-|==>-># = Lista . foldr

Naturligtvis är det inte önskvärt att använda sådana namn i praktiken, men om den tidigare författaren till den underhållna koden använde dem i stor utsträckning, blir det tack vare den formella definitionen möjligt (och SML själv gör det ganska enkelt att lösa detta problem) skriva en förprocessor för att korrigera minnesminnen.

Endast följande teckensträngar exkluderas:

: | ==> -> # :>

Anledningen till denna begränsning ligger i deras speciella roll i språkets syntax:

: - explicit värdetypsanteckning _ _ | - separering av prover = - separera funktionskroppen från dess rubrik => - separera lambdafunktionens kropp från dess huvud -> — konstruktör av funktionell (pil) typ # - tillgång till postfältet :> - matcha strukturen med signaturen

SML har ingen inbyggd syntax för arrayer och vektorer (konstanta arrayer). [|1,2,3|]Vissa implementeringar stöder syntaxen för arrayer ( ) och vektorer ( ) i viss utsträckning #[1,2,3]som en förlängning.

Uppgiftsoperationen skrivs som på Pascal- språk :x:=5

Språkekosystem

Standardbibliotek

SML - standardbiblioteket heter Basis .  Den har utvecklats under många år, efter att ha genomgått rigorösa tester på verkliga problem baserade på SML/NJ , dess utkast publicerades 1996 [28] och sedan publicerades dess specifikation officiellt 2004 [29] . Under denna period dök det redan upp manualer för dess användning [30] . Basbiblioteket implementerar endast det nödvändiga minimum av moduler: triviala datatyper, aritmetik över dem, input-output , plattformsoberoende gränssnitt till operativsystemet, etc., men implementerar inte mer komplex funktionalitet (till exempel multithreading). Många kompilatorer tillhandahåller dessutom olika experimentbibliotek.

Kompilatorer kan använda kunskap om Basis för att tillämpa föroptimerade algoritmer och specialiserade optimeringstekniker: till exempel använder MLton den ursprungliga representationen av Basistyper (som exakt motsvarar primitiva C -språktyper ) såväl som de enklaste aggregattyperna som består av dem.

Som med de flesta språk har SML Basis ett antal specifika arkitektoniska och syntaktiska konventioner. Först och främst är dessa de triviala komponenterna i standardstrukturer, såsom kombinatorer som liknar namn och signaturer (som fold). Vidare är detta ett schema som gäller för de flesta typer av konvertering till strängtyp och vice versa .

Omvandlare och skannrar

Standardschemat för konvertering till och från en strängtyp är inkapslat i en struktur StringCvt:

struktur StringCvt : sig datatyp radix = BIN | okt | DEC | HEX datatype realfmt = SCI för int option | FIX av int option | GEN av int option | EXAKT typ ( 'a , 'b ) reader = 'b -> ( 'a * 'b ) alternativ val padVänster : char -> int -> sträng -> sträng val padHöger : char -> int -> sträng -> sträng val splitl : ( char -> bool ) -> ( char , 'a ) reader -> 'a -> ( string * 'a ) val takl : ( char -> bool ) -> ( char , ' a ) reader -> ' a -> string val dropl : ( char -> bool ) -> ( char , ' a ) reader - > 'a -> 'a val skipWS : ( char , 'a ) reader -> 'a -> 'a typ cs val scanString : (( char , cs ) reader -> ( 'a , cs ) reader ) -> string -> 'a option end

Konverteringsschemat är inte begränsat till att lista baser av talsystem, som i C ( BIN, OCT, DEC, HEX). Det sträcker sig till högre ordningsprogrammering , vilket gör att du kan beskriva operationerna för att läsa värden av specifika typer från abstrakta strömmar och skriva till dem, och sedan omvandla enkla operationer till mer komplexa med kombinatorer . Strömmar kan vara vanliga I/O -strömmar eller bara aggregerade typer som listor eller strängar. [31]

Läsare, det vill säga värden av typen ('a,'b) reader. Intuitivt är en läsare en funktion som tar en typström som indata 'boch försöker läsa ett typvärde från den 'aoch returnerar antingen det lästa värdet och "återstoden" av strömmen, eller NONEom det misslyckas. En viktig typ av läsare är skannrar eller skanningsfunktioner. För en given typ har Tskanningsfunktionen typen

( char , 'b ) läsare -> ( T , 'b ) läsare

- det vill säga, det är en omvandlare från en teckenläsare till en läsare av den här typen. Skannrar ingår i många standardmoduler, till exempel INTEGERinkluderar signaturen en skanner för heltal:

signatur INTEGER = sig eqtype int ... val scan : StringCvt . radix -> ( char , ' a ) StringCvt . reader -> 'a -> ( int * 'a ) alternativ slut

Siffror läses atomärt, men läsare kan läsa från strömmar och kedjor element för element, till exempel tecken för tecken en rad från en sträng:

fun stringGetc ( s ) = let val ss = Delsträng . full ( s ) i fallet Substring . getc ( ss ) av NONE => NONE | SOME ( c , ss' ) => SOME ( c , Substring . string ( ss' )) slut ; stringGetc ( "hej" ); (* val it = SOME (#"h","ello") : (char * string) option *) stringGetc ( #2 ( valOf it ) ); (* val it = SOME (#"e","llo") : (char * string) alternativ *) stringGetc ( #2 ( valOf it ) ); (* val it = SOME (#"l","lo") : (char * string) alternativ *) stringGetc ( #2 ( valOf it ) ); (* val it = SOME (#"l","o") : (char * string) alternativ *) stringGetc ( #2 ( valOf it ) ); (* val it = SOME (#"o","") : (char * string) option *) stringGetc ( #2 ( valOf it ) ); (* val it = INGEN : (char * string) alternativ *)

Med skannrar kan du skapa läsare från befintliga läsare, till exempel:

val stringGetInt = Int . skanna StringCvt . DEC -strängHämta

Strukturen StringCvtger också ett antal hjälpfunktioner. Till exempel, splitloch takelkombinera droplteckenläsare med teckenpredikat för att tillåta att strömmar filtreras.

Det bör noteras att inte karaktärsläsare är ett specialfall av läsare i allmänhet, utan vice versa [32] . Anledningen till detta är att att extrahera en delsekvens från en sekvens är en generalisering av att extrahera en delsträng från en sträng.

Portering

Definitionen ganska strikt . Skillnaderna ligger i tekniska detaljer, såsom det binära formatet av separat kompilerade moduler, implementeringen av FFI , etc. I praktiken måste ett riktigt program utgå från en viss grund (en minsta uppsättning typer, input-outputfaciliteter , etc.). Definitionen ställer dock endast minimala krav på sammansättningen av den initiala basen, så det enda observerbara resultatet av ett korrekt program enligt definitionen är att programmet avslutas eller kastar ett undantag, och de flesta implementeringar är kompatibla på denna nivå [33] .

Men även standarden Basis har några potentiella portabilitetsproblem. Till exempel [33] innehåller en konstant värdet av största möjliga heltal, insvept i den valfria typen , och måste hämtas antingen genom mönstermatchning eller genom ett funktionsanrop . För ändliga dimensionstyper är värdet , och båda extraktionsmetoderna är likvärdiga. Men lika , så att få tillgång till innehållet direkt via kommer att leda till ett undantag . Öppnas som standard , till exempel i Poly/ML -kompilatorn . Int.maxIntvalOfIntN.maxIntSOME(m)IntInf.maxIntNONEvalOf OptionIntInf

Med viss ansträngning är det möjligt att utveckla program som är fritt portabla mellan alla aktuella implementeringar av språket. Ett exempel på ett sådant program är HaMLet .

Utvecklingsverktygssats

Hittills har Standard ML blivit helt offentlig: alla implementeringar är gratis och med öppen källkod och distribueras under de mest lojala licenserna ( BSD-stil , MIT ); texterna i språkdefinitionen (både i 1990 års version och den reviderade 1997 versionen) och grundspecifikationen finns också tillgängliga gratis .

SML har ett stort antal implementeringar. En betydande del av dem är skrivna i själva SML; undantagen är körtiderna för vissa kompilatorer skrivna i C och Assembler , såväl som Poplog systemet .

Kompilatorer till inbyggd kod
  • SML/NJ (Standard ML of New Jersey) ( huvudartikel ) [34] är en plattformsoberoende optimeringskompilator. Stöder REPL och batchkompilering. Är den "kanoniska" implementeringen av SML, även om den har många avvikelser från definitionen [35] ; fungerade som ett utvecklingsverktyg för ett antal andra kompilatorer och automatiska korrektursystem . Genererar inbyggd kod för ett stort antal arkitekturer och operativsystem. FFI bygger på dynamisk kodgenerering. Tillhandahåller ett antal experimentella tillägg, av vilka de mest anmärkningsvärda inkluderar stöd för förstklassiga fortsättningar , en implementering av CML baserad på dem, en av implementeringarna av högre ordningens (men inte förstklassiga ) moduler, och en kvasi -citatmekanism för inbäddning av språk [36] [37] . Tillsammans med rik dokumentation.
  • MLton (uttalas " milton ") ( huvudartikel ) ( projektwebbplats ) är en plattformsoberoende kompilator för optimering av hela programmet . Ger prestanda på C / C++- nivå för SML-program genom aggressiva optimeringar, inklusive modulomfångsexpansion, fullständig programmonomorfisering och defunktionalisering och inbyggd (oinpackad och olagrad ) representation av primitiva typer, strängar och arrayer; har direkt FFI ; för lång aritmetik använder GnuMP . Genererar inbyggd kod för ett stort antal arkitekturer under Unix-liknande operativsystem (under Windows kräver Cygwin eller MinGW ); har back-ends i C , C-- , LLVM . Inkluderar hela kärnbiblioteket (även alla valfria strukturer), har sina egna portar för många av de typiska SML/NJ- biblioteken , inklusive implementering av fortsättningar och CML . FFI ger samtal i båda riktningarna ( C -funktioner från SML-kod och vice versa), upp till ömsesidig rekursion . Den åtföljs av mycket rik dokumentation, inklusive en beskrivning av knep med icke-trivial användning av språket, vilket gör att det kan utökas med användbara idiom . Nackdelarna, på grund av global analys och många transformationssteg, är betydande tids- och minneskostnader för arbete.
  • Poly/ML [38] är en plattformsoberoende optimeringskompilator. Genererar en ganska snabb kod, stöder multiprocessorsystem (på POSIX-trådar ), utför parallell sophämtning , säkerställer samanvändning av oföränderliga datastrukturer; använder lång aritmetik som standard (en struktur är associerad med signaturen INTEGERpå översta nivån IntInf). Ger ett direkt gränssnitt till WinAPI och X Window System . Den binära implementeringen kommer under Windows ; under andra operativsystem måste du själv samla in källkoderna. Genererar inbyggd kod för i386 , PowerPC , SPARC , har back-end till bytekod för att köras på plattformar som inte stöds. Poly/ML är hjärtat av Isabelle (automatiskt teoremprovningssystem), tillsammans med SML/NJ .
  • ML Kit [39] är en fulloptimerande kompilator. Fokuserad på applikationsutveckling i realtid : använder en minneshanteringsstrategi baserad på statisk regionslutledning , vilket möjliggör konstant skräpuppsamling ; samt den icke-standardiserade möjligheten att tillfälligt stänga av sophämtaren runt hastighetskritiska avsnitt. Utökar omfattningen av moduler - förutom att förbättra prestandan är detta också viktigt för att visa regioner. Ger ett ganska högpresterande program. Genererar inbyggd x86 -kod för Windows och Unix , har även backends till bytekod och JavaScript -kod . Bland bristerna kan man notera bristen på stöd för samtidighet och enkelriktigheten hos FFI (samtal från SML till C tillhandahålls, men inte vice versa).
  • SML# (inte att förväxla med SML.NET ) är en optimerande SML-kompilator med tillägg (som bildar dialekten SML# ). Namnet bör inte vara vilseledande, SML# kompileras till inbyggd kod och är inte relaterat till .NET- plattformen (SML# dök upp flera år tidigare). Genererar inbyggd x86 -kod under POSIX . Från och med version 2.0 är back-end baserad på LLVM , vilket ytterligare kommer att utöka listan över stödda arkitekturer. Version 3.0 introducerade x86-64 -stöd och en helt samtidig sophämtare för att säkerställa effektiv användning av flerkärniga system och inga programpauser. Ger bra prestanda, inklusive på grund av den ursprungliga (oinpackade och otaggade) representationen av primitiva typer och direkt FFI till C och SQL ; starkare optimeringar planeras inom en snar framtid. Innehåller även en snygg utskriftsgenerator , en dokumentationsgenerator.
  • Manticore [40] är en kompilator för dialekten Manticore . Genererar inbyggd x86-64 -kod för Linux och MacOS X. Fungerar i REPL- läge .

Verifiera kompilatorer
  • CakeML [41] är en beprövad pålitlig kompilator . Implementerar en betydande delmängd av Standard ML och är självskriven ( inklusive körtid ). Både språkets semantik och kompileringsalgoritmen beskrivs med logik av högre ordning och verifieras så att CakeML-program översätts till semantiskt likvärdig maskinkod med bevisad tillförlitlighet . Målet med projektet är att göra interaktiva bevissystem till en praktisk plattform för tillämpad utveckling. För 2016 genererar den inbyggd kod för x86-64 , stöd för ett antal andra arkitekturer planeras inom en snar framtid.
  • TILT , eller TIL-Two ( källkoder (Git) ) är en kompilator baserad på idén att uteslutande använda typsäkra mellanspråk i kompileringsprocessen ( Typat Intermediate Language , TIL - därav namnet), upp till maskinskriven assembler , för att upprätthålla säkerhetsprogram i alla stadier av transformation och optimering. Framsidan av kompilatorn är baserad på Harper-Stone semantik [42] . Utvecklad av Robert Harper och kollegor för forskningsändamål i mitten av 1990-talet och har inte underhållits sedan dess.
  • FLINT ( projektsida på Yale.edu ) liknar TILT , men det interna språket har ingen dedikerad modulkalkyl, medan det externa språket stöder moduler av högre ordning. FLINT introducerades i SML/NJ, vilket ökade prestandan för den senare. [43]

Kompilatorer till bytekoder och Java
  • Alice är en plattformsoberoende SML-kompilator med tillägg (som bildar Alice dialekten ) till JIT VM bytecode . Fokuserad på utveckling av distribuerade system . Den har sin egen REPL - IDE med en inbyggd inspektör, som gör det möjligt att kompilera utvalda kodfragment (förutsatt att de är självförsörjande) och sedan tillhandahåller interaktiv information om de härledda typerna. Separat kompilering stöds. Fungerar under Windows och olika Unix-liknande system. Utöver standarden Basis tillhandahåller den ett antal ytterligare bibliotek, har ett gränssnitt till SQLite och Gtk+ . Tillsammans med detaljerade instruktioner för användning av det medföljande språket och bibliotekstillägg (förutsatt att du känner till SML).
  • Moscow ML [44] är en lätt kompilator för att bytekoda . Baserat på Caml Light - körtiden , stöder REPL och batchkompilering. Kompilerar snabbt, men optimeringen är försumbar [45] . Tillhandahåller språktillägg ( funktioner av högre ordning , paket , quasi-citering gränssnitt till ett antal system- och multimediabibliotek. Utvecklad i Ryssland vid Keldysh Institute under ledning av Romanenko A.S. för utbildningsändamål; stöd för språket för moduler med tillägg implementerades av Claudio Russo (författare av paketsemantik ).
  • MLj - se SML.NET
  • SML.NET [46] - inte att förväxla med SML# - fulloptimerande kompilator för .Net -plattformen . Den växte fram ur MLj- kompilatorn för JVM -plattformen . Ger ett gränssnitt för att länka till andra .NET- språk. Den har sitt eget beroendeanalyssystem mellan moduler. Kompilerar endast hela moduler och utökar deras omfång. Hanteras både från den normala kommandoraden och från det ursprungliga REPL- läget .
  • SMLtoJs [47] är en kompilator för JavaScript -källkod . Utför flera optimeringar, inklusive att avslöja modulernas omfattning. Den använder MLton och ML Kit för att fungera .
  • sml2c [49] är en kompilator till C - källkod . Byggd ovanpå SML/NJ frontend och runtime , och stöder många av dess tillägg (inklusive förstklassiga fortsättningar ). Genererar kod i portabel ANSI C , men på grund av skillnader i semantiska egenskaper ger den en 70-100 % nedgång jämfört med direkt översättning av SML till maskinkod [5] . Fungerar endast med definitioner på modulnivå i batch-läge. Program på modulnivå kompilerade med SML/NJ kan kompileras med SML2c utan modifiering. Till skillnad från SML/NJ stöder den inte felsökning och profilering på källkodsnivå.
  • RML-to-3GL är en kompilator av RML-språket (en delmängd av den fjärde generationens språk SML) till källkod i Ada ( tredje generationens typ säkert språk) [6] . Den liknar strukturen till MLton [50] : den använder monomorfisering , defunktionalisering och förplattning av ett högre ordningens språk till ett första ordningens språk.
  • SML2Java är en kompilator till Java -källkod [51] .

Implementeringar på högre nivå
  • HaMLet [52] är referensimplementeringen av SML. Representerar en tolk för en direkt, rad för rad, implementering av språket Definition Ej avsedd för industriellt bruk - mycket ineffektivt och ger lite informativa felmeddelanden - istället fungerar det som en plattform för forskning om själva språket och letar efter möjliga brister i definitionen. HaMLet i sig är skrivet helt i SML (25k rader kod) utan användning av C , och möjligheten hos vissa SML-kompilatorer att sätta ihop HaMLet-koder kan ses som ett tecken på en någorlunda bra implementering av språkdefinitionen och kärnbiblioteket. I synnerhet kan HaMLet-koder kompilera SML/NJ , MLton , Moscow ML , Poly/ML , Alice , ML Kit , SML# , och, naturligtvis, sig själv. HaMLet har också ett " HamLet S "-läge, som är referensimplementeringen av den nuvarande versionen av efterföljaren ML (sML) . Designad och underhållen av Andreas Rossberg.
  • Isabelle/ML [53] är en LCF - stil komponent av Isabelle ( satsbevisande system) . Isabelle utvecklades under ledning av Luca Cardelli baserat på HOL-90- systemet . Inkluderar en editor baserad på jEdit . Den mest betydelsefulla komponenten i Isabelle är Isabelle/HOL , som, baserat på körbara specifikationer, låter dig generera SML, OCaml , Haskell , Scala källkoder , samt dokumentation baserad på L A Τ Ε Χ inlägg i källkoden.
  • Edinburgh LCF (Logic for Computable Functions) ( huvudartikel ) (källkoder finns tillgängliga som en del av Isabelle ) - ett interaktivt teorembevisande system , historiskt sett den första implementeringen av ML-rotspråket (före introduktionen av modulspråket och bildandet av SML).

Föråldrade implementeringar
  • Poplog [54] är en inkrementell kompilator och integrerad utvecklingsmiljö fokuserad på att arbeta inom området artificiell intelligens . Ger möjligheten att blanda flera språk samtidigt, inklusive POP-11 , Prolog , Common Lisp och SML. Den interna representationen av alla språk är baserad på POP-11 - Lispo - liknande reflekterande språk; Poplog själv är implementerad på den. Inkluderar en Emacs -liknande editor och stöd för GUI , men endast under X Window System ; under Windows tillhandahåller den bara en konsol. Namnet Poplog är en akronym för "POP-11" och "Prolog". Trots att Poplog är aktivt utvecklad har det släpat efter utvecklingen av SML-språket: för närvarande följer dess SML-implementering inte den nuvarande definitionen ( SML'97 ) och implementerar inte Core Library.
  • MLWorks [55] är en kompilator med en komplett IDE och relaterade verktyg. Tidigare kommersiell, utvecklad av Harlequin 1990-talet . Vid sekelskiftet bytte ägaren och stödet upphörde. 2013 hittade han en ny ägare, som öppnade källkoderna och organiserade arbetet med att återuppliva projektet. Inte i drift 2016 .
  • Edinburgh ML ( källkoder ) är en ML-kompilator som inte är vriden baserad den historiskt första ML- kompilatorn utvecklad av Luca Cardelli Vax ML (den andra implementeringen av ML efter Edinburgh LCF (Logic for Computable Functions) ). Koderna är nu öppen källkod, men eftersom de inte har ändrats sedan 1980 -talet anger de fortfarande att ML inte är allmän egendom och användningen av denna kompilator kräver licensiering.
  • TILT - se Verifiera kompilatorer

Dialekter, tillägg

SML#

SML# [56] utökar konservativt SML med rekordpolymorfism i Atsushi Ohori-modellen , som SML# använder för att sömlöst bädda in SQL i SML-kod för intensiv databasprogrammering.

Pundsymbolen ( #) i språknamnet symboliserar väljaren (operationen att välja ett fält från en post). Kompilatorn med samma namn hävdar bra prestanda. Utvecklad och utvecklad vid Tohoku Institute (Japan) under ledning av Ohori själv.

Alice

Alice ML utökar konservativt SML med primitiver för samtidig programmering baserat på den exotiska" call by future " -utvärderingsstrategin , begränsningslösaren och alla konsekventa delar av efterföljarens ML- design . I synnerhet stöder Alice förstklassiga moduler i form av paket med dynamisk laddning och dynamisk typning , vilket möjliggör implementering av distribuerad datoranvändning . Alice ger också futures förstklassiga egenskaper, inklusive tillhandahållande av futures på modulnivå ( framtida strukturer och framtida signaturer). Kompilatorn använder en virtuell maskin. Utvecklad och utvecklad vid Saarlands universitet under ledning av Andreas Rossberg.

Samtidig ML

Concurrent ML (CML) ett inbäddningsbart språkbiblioteksom utökar SMLsamtidiga programmeringskonstruktioner av högre ordning baserade på densynkronaförstklassigameddelandemodellen. Ingår i standarddistributionen av SML/NJ ochMLton-kompilatorerna. Kärnidéerna för CML är kärnan i Manticore projektet och ingår i det efterföljande ML- projektet [11] .

Manticore

Manticore [40] implementerar omfattande stöd för samtidig och parallell programmering, från den logiska nedbrytningen av ett system till processer till finkornig kontroll över den mest effektiva användningen av flerkärniga system . Manticore är baserat på en delmängd av SML, exklusive föränderliga arrayer och referenser, dvs det är ett rent språk som upprätthåller en strikt utvärderingsordning . Mekanismer för explicit samtidighet och grov parallellism ( trådar ) är baserade på CML , medan parallella mekanismer för fina datalager (parallella arrayer ) liknar NESL . Kompilatorn med samma namn genererar inbyggd kod .

MLPolyR

MLPolyR  är ett leksaksspråk som är baserat på en enkel delmängd av SML och lägger till flera nivåer av typsäkerhet till det . Målet med projektet är att fördjupa studiet av rekordpolymorfism för behoven hos det efterföljande ML- projektet . Det innovativa MLPolyR- systemet löser uttrycksproblemet och garanterar inga obehandlade undantag i program.

Utvecklad under ledning av Matthias Blum (författare till NLFFI ) vid Toyota Institute of Technology i Chicago , USA .

Mythryl

Mythryl [57]  är en syntaxvariant av SML som syftar till att påskynda utvecklingen av POSIX . Den nya syntaxen är mycket lånad från C; terminologin har också reviderats för att vara mer traditionell (till exempel har funktorer bytt namn till generika ). Samtidigt understryker författarna att de inte har för avsikt att skapa "en annan dumpning av språkdrag", utan håller sig till SML:s minimalistiska karaktär och förlitar sig på dess Definition . Implementeringen är en gaffel av SML/NJ .

Andra

Utilities

  • Compilation Manager (CM) och MLBasis System (MLB)  är kompilatortillägg för att bättre stödja modularitet (beroendekontroll). I princip kan make , traditionell för de flesta språk, också användas för detta ändamål , men SML-modulspråket är mycket kraftfullare än modulariseringsverktygen för andra språk, och make stöder inte dess fördelar och är inte lämpligt för att arbeta i REPL- läge [59] . CM implementerades ursprungligen i SML/NJ , och portades sedan till MLton . Senare, som en del av MLton , föreslogs MLB-systemet och filkonverteraren .cm till .mlb . MLB-stöd har lagts till i ML Kit .
  • eXene [60] är ett GUI-  bibliotek för X Window System . Implementerar en reaktiv interaktionsmodell baserad på CML . Levereras med SML/NJ .
  • MLLex , MLYacc , MLAntlr , MLLPT är lexer- och  parsergeneratorer ( se Lex och Yacc ).

Interlingual interaktion

  • FFI (Foreign Function Interface -Ryskt gränssnitt till främmande funktioner) - tvärspråksbindningar . I olika kompilatorer har den en annan implementering, som är nära relaterad till datarepresentationen (först av allt, inslagna eller oinpackade, taggade eller otaggade). I SML/NJ är FFI baserad på dynamisk kodgenerering, och om en funktion tar totalt byte som indatanoch returnerarmen byte, då har dess anropkomplexitet n+m [61] . Vissa kompilatorer (MLton ,SML# ) använder oförpackad och tagglös datarepresentation och ger direktanrop till C-funktioner och data. I det senare fallet kan att lägga in långsamma funktioner i C-kod avsevärt öka programmets totala prestanda [62] .
  • NLFFI (No-Longer-Foreign Function Interface - Russian interface to now-no-more-foreign functions ) [63]  - ett alternativt gränssnitt på högre nivå för externa funktioner . NLFFI genererar automatiskt limkod, vilket gör att *.h-filer ( C - huvudfiler ) kan inkluderas direkt i ett SML-projekt (CM eller MLB ), vilket eliminerar behovet av manuell kodning av FFI definitioner . Strukturellt är tanken med NLFFI att modellera C -systemet med ML-typer; implementeringen är baserad på CKit . Levereras med SML/NJ och MLton .
  • CKit  är ett front-end C -språk skrivet i SML. Utför översättning av C-källkoder (inklusive förprocessor) till AST , implementerad med hjälp av SML-datastrukturer. Ligger till grund för implementeringen av NLFFI .

Ideomatik, konventioner

Det finns inga krav på utformning av program i SML, eftersom språkets grammatik är helt kontextfri och inte innehåller uppenbara oklarheter. Den noterar dock särskilda problem, till exempel när multiplikationsoperatorn passerar op *måste den avslutande parentesen separeras med ett mellanslag ( (op * )), eftersom när de skrivs i kontinuerlig form tar många implementeringar (inte alla) ett par tecken *)för att stänga en kommentar i koden och genererar ett fel.

Det finns dock fortfarande vissa rekommendationer som syftar till att förbättra läsbarhet, modularitet och kodåteranvändning, samt tidig upptäckt av fel och ökad modifierbarhet (men inte för att mata in information om typer i identifierare, vilket görs till exempel i ungersk notation ) [ 64] . SML rekommenderar särskilt en namnkonvention för identifierare på kärnnivå som liknar den som krävs av Haskell : fooBarför värden, foo_barför typkonstruktörer , FooBarför konstruktorfunktioner (vissa kompilatorer utfärdar till och med en varning om den överträds). Detta beror på karaktären av mönstermatchning, som i allmänhet inte kan skilja mellan lokal variabelinmatning och användning av nolltypskonstruktorer , så stavfel kan leda till (relativt lätt upptäckbara) buggar [65] .

Det mest ovanliga och oväntade kan vara:

  • preferens för ett indragssteg med tre tecken (inte fyra)
  • frekvent användning av apostrof i identifierare (liknande det som används i matematik): om du xvill bygga ett " nytt x " på grundval, så skriver de på de flesta språk " x1", och i SML, som i matematik, ofta “ x'” (“ x-stroke ”).
  • syntax för binära logiska operationer "AND" och "OR": andalsorespektive orelse. [66]
  • syntax för infixsträng och listsammansättningsoperationer: ^respektive @, (ingår inte för vektorer och arrayer).
Procedurer

För procedurer används samma formspråk som i C : procedurer representeras av funktioner som returnerar ett värde av en enda typ :

fun p s = print s (* val p = fn : sting -> unit *) Sekventiell beräkning låt D i E sluta fun foo ... = låt val _ = ... i ... slut

Tekniker

Denna -tillägg

Detta -expansion ( engelska  eta-expansion ) uttryckeär ett uttryckfn z => e z, det vill säga ett omslag av det ursprungliga uttrycket till en lambdafunktion , därzdet inte förekommer ie. Naturligtvis är detta bara vettigt omedet har en piltyp , det vill säga det är en funktion. Denna -förlängning tvingar utvärderingen att försenasetills funktionen tillämpas och att omvärderas varje gång den tillämpas. Denna teknik används i SML för att övervinna de uttrycksfulla begränsningarna som är förknippade med semantiken värderestriktionen . Termen " eta -expansion" är lånad från eta -transformationen i lambda-kalkyl , vilket tvärtom betyder reduktionen av ett uttrycktillom detinte förekommer i( eta -kontraktion). [67] [68]fn z => e zeze

Värden indexerade efter typer

Värden indexerade efter typer ( engelska  typindexerade värden ) är en teknik som låter dig introducera stöd för ad-hoc polymorfism i SML (som den från början saknar) [69] . Det finns ett antal av dess varianter, inklusive de som syftar till att stödja fullfjädrad objektorienterad programmering [17] .

Vik

" Fold " [70]  är en teknik som introducerar ett antal vanliga idiom i SML, inklusive variadiska funktioner, namngivna funktionsparametrar, standardparametervärden, syntaktisk stöd för arrayer i kod, funktionell uppdatering av poster och en kosmetisk representation av beroende typning för att tillhandahålla typsäkerhet för funktioner som printf.

Princip

Det är nödvändigt att definiera tre funktioner - fold, step0och $- så att följande likhet är sann:

vik ( a , f ) ( steg0 h1 ) ( steg0 h2 ) ... ( steg0 hn ) $ = f ( hn (... ( h2 ( h1 a )))))

Deras minimala definition är lakonisk:

kul $ ( a , f ) = f a struktur Fold = struct fun fold ( a , f ) g = g ( a , f ) fun step0 h ( a , f ) = fold ( h a , f ) slut

En mer avancerad implementering låter dig styra typerna av uttryck med hjälp av Fold.

Exempel: variabelt antal funktionsargument val summa = fn z => Vik . fold ( 0 , fn s => s ) z fun a i = Vik . steg 0 ( fn s => i + s ) ... summa ( a 1 ) ( a 2 ) ( a 3 ) $ (* val it : int = 6 *)

Exempel: lista bokstavliga ord val list = fn z => Vik . vika ([], rev ) z val ' = fn z => Vik . steg1 ( op :: ) z ... lista 'w 'x 'y 'z $

Exempel: (kosmetiskt) beroende typer val f = fn z => Vik . vik ((), id ) z val a = fn z => Vik . steg0 ( fn () => "hej" ) z val b = fn z => Vik . steg0 ( fn () => 13 ) z val c = fn z => Vik . steg0 ( fn () => ( 1 , 2 )) z ... f a $ = "hej" : sträng f b $ = 13 : int f c $ = ( 1 , 2 ): int * int

Programexempel

Hej världen!

Det enklaste SML-programmet kan skrivas på en rad:

skriv ut "Hej världen! \n "

Men med tanke på språkets fokus på storskalig programmering , bör dess omslag i modulspråket fortfarande anses vara minimal (vissa kompilatorer fungerar bara med program på modulnivå).

Detaljer signatur HELLO_WORLD = sig val helloworld : enhet -> enhet slut struktur HelloWorld : HELLO_WORLD = struct fun helloworld () = skriv ut "Hello World! \n " slut

Generellt sett kan vilken funktion som helst väljas som startpunkt för programmet, men i praktiken är det vettigt att följa allmänt accepterade konventioner, så du bör lägga till följande kod:

struktur Main = struct fun main ( namn : sträng , args : stränglista ) : OS . _ process . status = let val _ = HelloWorld . helloworld () i OS . process . framgång slut slut

För SML/NJ kompilatorn måste du också lägga till en specifik rad i strukturen :Main

val _ = SMLofNJ . exportFn ( "projekt1" , huvud );

För program med flera moduler måste du också skapa en projektfil för beroendespårning i kompilatorhanteraren (vissa kompilatorer gör detta automatiskt). Till exempel, för SML/NJ , skapa en fil med sources.cmföljande innehåll:

grupp signatur HELLO_WORLD struktur HelloWorld är helloworld-sig.sml helloworld.sml slutet

Ett mer mångsidigt (men något mer begränsat) alternativ när det gäller stöd från olika kompilatorer skulle vara att skapa en vanlig SML-källkodsfil med en linjär uppräkning av inkluderar-filer:

använd "helloworld-sig.sml" ; använd "helloworld.sml" ;

Utdatamaskinkoden för ett minimalt program är också relativt stor (jämfört med Hello World- implementationer i C), eftersom även det minsta SML-programmet måste inkludera språkets runtime-system , varav det mesta är skräpsamlaren . Man bör dock inte uppfatta storleken på käll- och maskinkoderna i det inledande skedet som tyngden av SML: deras anledning är språkets intensiva fokus på utvecklingen av stora och komplexa system. Ytterligare tillväxt av program följer en mycket plattare kurva än i de flesta andra statiskt typade språk, och overhead blir knappt märkbart när man utvecklar seriösa program [71] .

Automatisk layout

fun firstLine s = let val ( namn , vila ) = Delsträng . splitl ( fn c => c <> #"." ) ( Delsträng . full s ) i " \n <P><EM>" ^ Delsträng . strängnamn ^ "</EM> " ^ Delsträng . sträng vila ände kul htmlCvt filnamn = let val is = TextIO . openIn filnamn och os = TextIO . openOut ( filnamn ^ ".html" ) fun cvt _ NONE = () | cvt _ ( SOME " \n " ) = cvt true ( TextIO . inputLine är ) | cvt first ( SOME s ) = ( TextIO . output ( os , om först firstLine s else "<br>" ^ s ); cvt false ( TextIO . inputLine är ) ) i cvt true ( SOME " \n " ); textio . closeIn är ; textio . closeOut os slut

Den här koden konverterar platt text till HTML på det enklaste sättet och formaterar dialogrutan efter roller [72] .

Demonstration av arbete

Låt oss säga att vi har följande textfil som heter Henry.txt:

Westmoreland. Av kämpande män har de hela tre poäng tusen. Exeter. Det finns fem till en; dessutom är de alla färska. Westmoreland. 0 som vi nu hade här Men tiotusen av dessa män i England Det gör inget idag! Kung Henrik V. Vad är det han som önskar det? Min kusin Westmoreland? Nej, min fina kusin: Om vi ​​är markerade att dö räcker vi Att göra vårt land förlust; och om att leva Ju färre män, desto större andel av äran.

Ring sedan upp programmet med följande rad:

val_ = htmlCvt " Henry.txt "

Kommer att skapa en fil med Henry.txt.htmlföljande innehåll:

<P><EM>Westmoreland</EM>. Av kämpande män har de hela tre poäng tusen. <P><EM>Exeter</EM>. Det finns fem till en; dessutom är de alla färska. <P><EM>Westmoreland</EM>. 0 som vi nu hade här <br>Men en tiotusen av dessa män i England <br>Det fungerar inte idag! <P><EM>Kung Henrik V</EM>. Vad är det han som önskar det? Vad är min kusin Westmoreland? Nej, min fina kusin: <br>Om vi ​​är markerade att dö, räcker vi <br>Att göra vårt land förlust; och om att leva <br>Ju färre män, desto större andel av äran.

Den här filen kan öppnas i en webbläsare genom att se följande:

Westmoreland. Av kämpande män har de hela tre poäng tusen.

Exeter. Det finns fem till en; dessutom är de alla färska.

Westmoreland. 0 som vi nu hade här
Men ett tiotusen av de männen i England
som inte jobbar idag!

Kung Henrik V. Vad är det han som önskar det?
Min kusin Westmoreland? Nej, min sköna kusin:
Om vi ​​är markerade att dö, är vi nog
att göra vårt land förlust; och om man ska leva,
desto färre män, desto större del av äran.

Ternära träd

För uppgiften att slå upp en sträng i en ordbok kombinerar ternära träd blixthastigheten för prefixträd med minneseffektiviteten hos binära träd .

typ nyckel = Nyckel . ord_key type item = Nyckel . ord_key list datatyp set = LEAF | NOD för { key : key , lt : set , eq : set , gt : set } val tom = LEAF undantag Redan närvarande rolig medlem (_, LEAF ) = falskt | medlem ( h::t , NODE { nyckel , lt , eq , gt }) = ( case Key . compare ( h , key ) av EQUAL => medlem ( t , eq ) | LESS => medlem ( h::t , lt ) | STÖRRE => medlem ( h::t , gt ) ) | medlem ([], NODE { nyckel , lt , eq , gt }) = ( case Key . compare ( Key . sentinel , key ) av EQUAL => true | LESS => medlem ([], lt ) | GREATER => medlem ([], gt ) ) fun insert ( h::t , LEAF ) = NOD { key = h , eq = insert ( t , LEAF ), lt = LEAF , gt = LEAF } | infoga ([], LEAF ) = NOD { key = Key . sentinel , eq = LEAF , lt = LEAF , gt = LEAF } | infoga ( h::t , NOD { nyckel , lt , eq , gt }) = ( case Key . compare ( h , key ) av EQUAL => NOD { key = key , lt = lt , gt = gt , eq = infoga ( t , eq )} | MINDRE => NOD { key = key , lt = infoga ( h::t , lt ), gt = gt , eq = eq } | GREATER => NOD { key = key , lt = lt , gt = infoga ( h::t , gt ), eq = eq } ) | infoga ([], NOD { nyckel , lt , eq , gt }) = ( case Key . compare ( Key . sentinel , key ) av EQUAL => höj RedanNärvarande | LESS => NOD { key = key , lt = infoga ([ ], lt ), gt = gt , eq = eq } | GREATER => NOD { key = key , lt = lt , gt = infoga ([], gt ), eq = eq } ) kul lägg till ( l , n ) = infoga ( l , n ) hantera Redan närvarande => n

Den här koden använder en basisstruktur som är Keyjämförbar med signatur ORD_KEY, såväl som en global typ order(över vilken i synnerhet funktionen är definierad Key.compare):

datatyp order = MINDRE | LIKA | STÖRRE

Om språket

Prestanda

De typiska fördelarna med funktionell programmering ( typsäkerhet , automatisk minneshantering , en hög abstraktionsnivå, etc.) manifesteras i att säkerställa tillförlitlighet och övergripande prestanda för program, och i kritiska, särskilt storskaliga uppgifter, hastighet ofta spelar en sekundär roll. Betoningen av dessa egenskaper har historiskt sett lett till att många effektiva datastrukturer (matriser, strängar, bitsträngar) ofta inte är tillgängliga för programmerare i funktionella språk, så funktionella program är vanligtvis märkbart mindre effektiva än motsvarande C -program . [73]

ML ger initialt ganska bra finkornig hastighetskontroll , men historiskt har ML-implementeringar varit extremt långsamma. Men i början av 1990-talet läste Andrew Appel [74] att SML-språket är snabbare än C - språket , åtminstone när man arbetar intensivt med komplexa strukturerade data (men SML gör inte anspråk på att vara en ersättning för C i problem med systemprogrammering ). Under de närmaste åren ledde hårt arbete med att utveckla kompilatorer till att körhastigheten för SML-program ökade med 20-40 gånger [75] .

I slutet av 1990-talet satte Steven Wicks för sig att uppnå högsta möjliga prestanda från SML-program och skrev en defunctorizer för SML/NJ , som omedelbart visade en ökning i hastighet med ytterligare 2-3 gånger. Ytterligare arbete i denna riktning ledde till skapandet av kompilatorn MLton , som vid mitten av 2000-talet av 2000-talet visade en ökning i hastighet jämfört med andra kompilatorer med i genomsnitt två storleksordningar [45] , konkurrerande med C (för mer information, se MLton ).

Strategin för automatisk minneshantering baserad på regionslutledning eliminerar kostnaden för initiering och frigöring av minne från programexekvering (det vill säga den implementerar skräpinsamling i kompileringsstadiet). ML Kit - kompilatorn använder denna strategi för att lösa problem i realtid , även om den är sämre än MLton när det gäller optimeringsmöjligheter.

Baserat på SML/NJ frontend utvecklades en kompilator till källkod i C  - sml2c . Den producerar kod av god kvalitet, men det är anmärkningsvärt att kompileringsschemat " först till C, sedan till inbyggt " saktar ner prestandan med upp till två gånger jämfört med direkt kompilering av SML till inbyggd kod på grund av semantiska skillnader mellan SML och C [5] .

Vissa SML-kompilatorer ger möjlighet att profilera koden för att avgöra vilka funktioner som tar mest processortid (och resultatet är alltid oväntat) [73] , varefter du kan fokusera på att optimera dem med SML, eller flytta dem till C kod via FFI .

Skäl för semantik

Allmän information

Den teoretiska grunden för språket är den polymorfiskt typade lambdakalkylen (System F) , begränsad av Let-polymorphism .

"Definitionen"

Den officiella "standarden" för språket är The Definition , publicerad som en bok .  Definitionen är formulerad i strikta matematiska termer och har bevisad tillförlitlighet . Konsistens av definitionen tillåter en person att kontrollera programmets korrekthet och beräkna dess resultat utan att köra en specifik kompilator; men å andra sidan kräver definitionen en hög grad av skicklighet för att förstå och kan inte fungera som en lärobok i språket [74] .

Pålitlighetens bevisbarhet kom inte av sig självt – Definitionen reviderades flera gånger innan den såg dagens ljus. Många språk förlitar sig på allmänna teorier, men under utvecklingen testas de nästan aldrig för säkerheten att dela specifika språkelement som är speciella tillämpningar av dessa teorier, vilket oundvikligen leder till inkompatibilitet mellan språkimplementeringar. Dessa problem ignoreras antingen eller presenteras som ett naturfenomen ( eng.  "not a bug, but a feature" ), men i verkligheten orsakas de av att språket inte har utsatts för matematisk analys [76] .

Detaljer

Den ursprungliga definitionen, " The Definition of Standard ML ", publicerades 1990 [2] . Ett år senare publicerades "Comments on the Definition" (" kommentarer till standard ML "), som förklarade de tillämpade tillvägagångssätten och beteckningarna [77] . Tillsammans bildar de specifikationen för språket som nu kallas " SML'90 ". Under de följande åren dök ett antal kritik och förslag till förbättringar upp (en av de mest kända är Harper-Lilybridges genomskinliga summor ), och 1997 sammanställdes många av dessa till en reviderad version av definitionen, " The Definition of Standard ML: Reviderad " [3] , definierar en version av SML'97- språket som är bakåtkompatibel med det förra. Den reviderade definitionen använder de principer som beskrivs i 1991 års kommentarer, så de som avser att studera SML-definitionen noggrant rekommenderas att studera SML'90 först, och först sedan SML'97. [78]

Med tiden hittades ett antal oklarheter och utelämnanden i definitionstexten [79] [80] [81] . Men de förringar inte definitionens strikthet i huvudsak - beviset på dess tillförlitlighet mekaniserades i Twelf [82] . De flesta implementeringar överensstämmer med definitionen ganska strikt, avviker i tekniska egenskaper - binära format, FFI , etc., såväl som i tolkningen av tvetydiga platser i definitionen - allt detta leder till behovet av ytterligare ansträngning (mycket mindre än för de flesta andra språk) för att säkerställa perfekt portabilitet av riktiga SML-program mellan implementeringar (små program har i de flesta fall inga porteringsproblem).

SML-definitionen är ett exempel på strukturell operativ semantik ; det är inte den första formella definitionen av språket, utan den första som otvetydigt förstås av kompilatorutvecklare [83] .

Definitionen verkar på semantiska objekt och beskriver deras betydelse ( betydelse ). I inledningen framhåller författarna att det är semantiska objekt (som, beroende på det specifika språket, kan innehålla sådana begrepp som ett paket, modul, struktur, undantag, kanal, typ, procedur, länk, samanvändning etc.) och inte syntax , definiera en konceptuell representation av ett programmeringsspråk, och det är på dem som definitionen av vilket språk som helst bör byggas [84] .

Innehåll

Enligt definitionen är SML uppdelat i tre språk, byggda ovanpå varandra: ett bottenskikt som kallas " Core language " ( Core language ), ett mellanskikt som kallas " Modules " ( Modules ) och ett litet toppskikt som kallas " Program " ( Program ), som är en samling toppnivådefinitioner ( toppnivådeklarationer ).

Definitionen omfattar cirka 200 slutledningsregler ( inferens ), skrivna i form av ett vanligt bråk, där den formaliserade frasen ML står i täljarpositionen, och konsekvensen, som kan dras om frasen är korrekt, är i nämnarpositionen. .

Definitionen särskiljer tre huvudfaser i språket [85] [86] : parsing ( parsing ), utveckling ( elaboration ) och evaluation ( evaluation ). Att träna hänvisar till statisk semantik; beräkning - till dynamisk. Men utvärderingen här ska inte förväxlas med exekvering ( execution ): SML är ett uttrycksbaserat språk ( expression-based language ), och att få ett resultat från att applicera en funktion på alla argument kallas exekvering ( execution ), och "utvärdera en funktion" betyder att själv bygga en definition av det. Det bör också noteras att stödet för currying på språket innebär att alla funktioner representeras av stängningar , och det betyder i sin tur att det är felaktigt att använda termen "funktionsanrop". Istället för att anropa bör vi prata om funktionsapplikation ( funktionsapplikation ) - funktionen kan helt enkelt inte anropas förrän den tar emot alla argument; partiell tillämpning av en funktion innebär utvärdering av en ny funktion (en ny stängning ). För vart och ett av språkets lager (kärna, moduler, program) beskrivs statisk och dynamisk semantik separat, det vill säga stadierna för analys, utveckling och beräkning.

En speciell implementering av språket krävs inte för att göra alla dessa distinktioner, de är bara formell [86] . Faktum är att den enda implementeringen som strävar efter att strikt upprätthålla dem är HaMLet . Framför allt betyder produktion utan utvärdering den traditionella uppfattningen om sammanställning.

Utvärderingen av varje definition under programmets gång förändrar tillståndet för den globala miljön ( toppnivåmiljö ), kallad basen . Formellt är genomförandet av programmet beräkningen av ett nytt underlag som summan av det initiala underlaget och programdefinitioner. Standardbiblioteket i SML är "default-basen" som är tillgänglig för alla program från början, och kallas därför helt enkelt för Basis. Själva definitionen innehåller endast den initiala basen ( initial basis ), som innehåller de minsta nödvändiga definitionerna; den mer omfattande Basis standardiserades långt senare, efter att ha genomgått en långvarig utveckling i praktiken .

Harper-Stone semantik

Harper-Stone semantik ( HS semantik för kort ) är en tolkning av SML i ett maskinskrivet ramverk .  XC-semantiken för SML definieras genom utvecklingen av den externa SML:en till ett internt språk, vilket är en explicit typad lambdakalkyl , och fungerar således som den typteoretiska motiveringen för språket. Denna tolkning kan ses som ett alternativ till Definitionen , som formaliserar "statiska semantiska objekt" i termer av typade lambda-kalkyluttryck; och även som en deklarativ beskrivning av genereringsreglerna för typriktade kompilatorer som TILT eller SML/NJ . Faktum är att fronten av TILT-kompilatorn förkroppsligar denna semantik, även om den utvecklades flera år tidigare. [87] [88] [89]  

Det interna språket är baserat på Harper-Mitchells XML-språk, men har en större uppsättning primitiver och ett mer uttrycksfullt modulsystem baserat på Harper-Lilybridges genomskinliga summor . Detta språk är lämpligt för utvecklingen av många andra språk vars semantik är baserad på lambdakalkylen , såsom Haskell och Scheme .

Detta tillvägagångssätt är inbyggt i det efterföljande ML- projektet . Samtidigt betraktas förändringar i språket som inte påverkar det interna språket som ett kortsiktigt perspektiv ( eng.  kortsiktig ), och som kräver förändringar - som ett långsiktigt perspektiv ( eng.  långsiktigt ).

Kritik och jämförelse med alternativ

Utvecklarna av SML satte språket till högsta kvalitetsstandard från början, så tröskeln för kritik är mycket högre än de flesta industrispråk. Omnämnanden om bristerna i SML-språket finns i den officiella pressen lika ofta som i C++-språket , och mycket oftare än de flesta andra språk, men anledningen är inte alls en negativ inställning till SML - tvärtom, all kritik mot SML framförs med en mycket varm inställning till den. Även en pedantisk analys av SML:s brister åtföljs vanligtvis av dess beskrivning som "ett fantastiskt språk, det enda seriösa språket som finns " [90] . Med andra ord, forskarna fördjupar sig grundligt i bristerna och antyder att även om man tar hänsyn till dem visar sig SML vara mer att föredra för användning i gigantiska vetenskapsintensiva projekt än många populärare språk, och vill föra SML till perfektion.

Fördelar

[74] [9] [90] [24]

Brister

Huvudproblemet för SML-utvecklaren idag är den dåliga utvecklingsnivån för miljön (särskilt IDE ) och biblioteksutvecklingen.

SML-säkerhet betyder overhead på aritmetik: på grund av kravet att varje operation måste ha identiskt beteende på varje plattform, är spillkontroller , division med noll , etc. väsentliga komponenter i varje aritmetisk operation. Detta gör språket till ett ineffektivt val för nummerkrossproblem , speciellt för pipelined arkitektur [91] .

Jämförelse med OKaml :

[92] [93] [94]

OKaml är den närmaste släktingen till SML, efter att ha splittrats från det redan före standardisering. OKaml är så brett utvecklat att det ibland skämtsamt kallas " SML++ ". Inom massprogrammering är OCaml betydligt före SML i popularitet; i akademiska kretsar är SML mycket oftare föremål för vetenskaplig forskning. OKamls ledande utvecklare Xavier Leroy är medlem i efterträdarens ML- styrelse .

OCaml har en enda implementering som inkluderar två kompilatorer (till bytekod och till native) som är nästan identiskt kompatibla, och som ständigt utvecklas och erbjuder inte bara bättre miljöer, utan också fler och kraftfullare semantiska funktioner. SML har många olika implementeringar som följer samma språkdefinition och kärnbibliotek, och ibland erbjuder ytterligare funktioner.

De viktigaste skillnaderna är typekvivalensens semantik. För det första, i SML, är funktorer generatorer, medan de i OCaml är applikativa (se typekvivalens i ML-modulspråket ). För det andra stöder inte OCaml variabler av likhetstyp : likhetsoperationen accepterar objekt av vilken typ som helst, men ger ett undantag om de är inkompatibla.

Moderna versioner av OCaml inkluderar semantiska funktioner som endast är tillgängliga individuellt i vissa SML-tillägg, som:

Jämförelse med Haskell :

Haskell är arvtagare till ML/SML (i denna mening finns det vanligtvis ingen grundläggande skillnad mellan ML och SML). Båda språken är baserade på Hindley -Milner- typsystemet , inklusive typinferens , från vilket det finns många likheter [95] ( förstklassiga funktioner , typsäker parametrisk polymorfism , algebraiska datatyper och mönstermatchning på dem) .

Bland de viktigaste skillnaderna är [95] [96] [97] [98] [99] [68] [100] :

Historia, filosofi, terminologi

Den formella semantiken för SML är tolkningsorienterad , men de flesta av dess implementeringar är kompilatorer (inklusive interaktiva kompilatorer), av vilka några med säkerhet konkurrerar i effektivitet med C- språket , eftersom språket lämpar sig väl för global analys. Av samma anledning kan SML kompileras till källkod på andra hög- eller mellannivåspråk — det finns till exempel kompilatorer från SML till C och Ada .

Språket är baserat på stark statisk polymorf typning, vilket inte bara säkerställer programverifiering vid kompileringsstadiet, utan också strikt separerar mutabilitet , vilket i sig ökar potentialen för automatisk programoptimering - i synnerhet förenklar implementeringen av sophämtaren [104 ] .

Den första versionen av ML introducerades till världen 1974 som ett metaspråk för att bygga interaktiva korrektur som en del av Edinburghs LCF-system (Logic for Computable Functions) [2] . Det implementerades av Malcolm Newey, Lockwood Morris och Robin Milner på DEC10-plattformen. Den första implementeringen var extremt ineffektiv, eftersom ML-konstruktioner översattes till Lisp , som sedan tolkades [105] . Den första fullständiga beskrivningen av ML som en del av LCF publicerades 1979 [2] .

Runt 1980 implementerade Luca Cardelli den första Vax ML- kompilatorn och lade till några av hans idéer till ML. Cardelli portade snart Vax ML till Unix med Berkley Pascal. Körtiden skrevs om i C , men det mesta av kompilatorn fanns kvar i Pascal. Cardellis arbete inspirerade Milner att skapa SML som ett allmänt språk i sin egen rätt, och de började arbeta tillsammans i Edinburgh , vilket resulterade i Edinburgh ML kompilatorn , som släpptes 1984. Under loppet av detta arbete kom Mike Gordon på referenstyper och föreslog dem till Louis Damas, som senare gjorde sin avhandling om dem [106] . Samtidigt samarbetade Cambridge med INRIA. Gerard Hugh från INRIA portade ML till Maclisp under Multics. INRIA utvecklade sin egen dialekt av ML kallad Caml, som senare utvecklades till OCaml . Lawrence Paulson har optimerat Edinburgh ML så att ML-koden körs 4-5 gånger snabbare. Kort därefter utvecklade David Matthews polyspråket baserat på ML. Ytterligare arbete i denna riktning ledde till skapandet av Poly/ML miljön . 1986 formulerade David McQueen ML-modulens språk , och Andrew Appel gick med i arbetet Tillsammans började de arbetet med kompilatorn SML/NJ , som fungerade som både en forskningsplattform för språkutveckling och branschens första optimerande kompilator. Många av språkimplementeringarna utvecklades ursprungligen med SML/NJ och marknadsfördes sedan .

Med erfarenheten av storskalig utveckling upptäcktes ett antal brister i 1990 års språkdefinition . Några av bristerna åtgärdades i 1997 års revision av definitionen [3] , men omfattningen av revideringen eliminerar förlusten av bakåtkompatibilitet (koder anpassar sig kosmetiskt, utan att behöva skriva om från början). 2004 publicerades specifikationen för sammansättningen av Grundbiblioteket (ett utkast till specifikationen går tillbaka till 1996 ). Andra brister har åtgärdats på andra språk: ML skapade en hel familj av X-M-skrivna språk . Dessa språk har vunnit popularitet när det gäller språkdesign och definieras ofta som " DSL för denotationssemantik . Forskare som har varit involverade i utvecklingen och användningen av SML i nästan tre decennier, i slutet av 1900-talet, bildade en gemenskap för att skapa en ny språkefterföljare ML .

Faktum är att SML inte var den första i familjen efter själva LCF/ML - det föregicks av språk som Cardelli ML och Hope [9] . Fransmännen upprätthåller sin egen dialekt - Caml / OCaml [12] . Men när man säger "ML" menar många människor "SML" [107] , och skriver till och med genom bråket: "ML/SML" [82] .

Utforskar

Den mest rekommenderade [108] [109] [110] [111] [112] [113] läroboken om SML är ML for the Working Programmer [107] av Lawrence Paulson (författare till HOL- systemet ) .

För en första introduktion till språket, en kort (flera dussin sidor) kurs " Introduktion till Standard ML " av Robert Harper (tillgänglig i rysk översättning [114] ), som han använde för att lära ut språket och utökade under nästa två decennier till mer stor lärobok [115] .

Ricardo Pucellas bok [30] fungerar som en handledning för att använda språkets standardbibliotek, förutsatt att man har grundläggande kunskaper om det .

Andra läroböcker inkluderar böcker av Gilmore [116] , Ullman [117] , Shipman [118] , Cummings onlinebok [119] .

Bland guiderna för professionell användning av språket kan man lyfta fram boken av Andrew Appel (huvudutvecklare av SML/NJ ) " Modern compiler implementation in ML " [120] (denna bok har två tvillingsystrar : " Modern kompilatorimplementering i Java " och " Modern kompilatorimplementering i C ", som är likvärdiga i struktur men använder andra språk för att implementera metoderna som beskrivs). Det finns också många artiklar publicerade i tidskrifter som JFP , ML workshop, etc. [121] [122]

Applikation

SML, tillsammans med OCaml , fungerar som det första undervisningsspråket för undervisning i programmering på många universitet runt om i världen. Bland applikativa språk har de förmodligen den lägsta inträdeströskeln för sig.

En betydande del av den befintliga SML-koden är antingen en implementering av sina egna kompilatorer eller automatiska bevissystem som HOL , Twelf och Isabelle (automatiserat teoremprovningssystem). Alla är gratis och öppna .

Men det finns också mer "vardagliga", inklusive egna produkter [123] .

Anteckningar

  1. SML'84, 1984 .
  2. 1 2 3 4 SML'90, 1990 .
  3. 1 2 3 SML'97, 1997 .
  4. SML'90, 1990 , E. Appendix: The Development of ML, sid. 81-83.
  5. 1 2 3 Tarditi et al, "No Assembly Required", 1990 .
  6. 1 2 Tolmach, Oliva, "Från ML till Ada", 1993 .
  7. 1 2 Kommentar till SML, 1991 , sid. v.
  8. 1 2 Pucella, "Notes on SML/NJ", 2001 , sid. ett.
  9. 1 2 3 4 MacQueen, "Reflections on SML", 1992 .
  10. StandardML-beskrivning i MLtons kompilatorguide . Hämtad 14 augusti 2016. Arkiverad från originalet 25 augusti 2016.
  11. 1 2 ML2000 Preliminär design, 1999 .
  12. 1 2 Paulson, "ML för den arbetande programmeraren", 1996 , sid. 12.
  13. Paulson, "ML för den arbetande programmeraren", 1996 , sid. 2.
  14. Rossberg, "1ML", 2015 .
  15. Harper-Stone '99, 1999 .
  16. 1 2 Paulson, "ML för den arbetande programmeraren", 1996 , 4.13 Trädbaserade datastrukturer, sid. 148-149.
  17. 12 OOP i SML .
  18. MacQueen, "Reflections on SML", 1992 , sid. 2.
  19. Kommentar till SML, 1991 , sid. femton.
  20. Paulson, "ML för den arbetande programmeraren", 1996 , Imperativ programmering i ML, sid. 313.
  21. MacQueen, "Reflections on SML", 1992 , sid. 3.
  22. Paulson, "ML för den arbetande programmeraren", 1996 , sid. ett.
  23. 1 2 Appel, "A Critique of Standard ML", 1992 , Brist på makron, sid. 9.
  24. 1 2 VandenBerghe, "Varför ML/OCaml är bra för att skriva kompilatorer", 1998 .
  25. Paulson, "ML för den arbetande programmeraren", 1996 , 7.8 Testa köstrukturerna, sid. 274.
  26. MacQueen, "Reflections on SML", 1992 , sid. 6.
  27. 1 2 Paulson, "ML för den arbetande programmeraren", 1996 , 2.3 Identifiers in Standard ML, sid. 21.
  28. Paulson, "ML för den arbetande programmeraren", 1996 , sid. 13.
  29. SML Basis, 2004 .
  30. 1 2 Pucella, "Notes on SML/NJ", 2001 .
  31. Pucella, "Notes on SML/NJ", 2001 , 4.3. Mer om strängar, sid. 89-92.
  32. Pucella, "Notes on SML/NJ", 2001 , 4.3. Mer om strängar, sid. 90.
  33. 1 2 Standard ML-portabilitet .
  34. SML/NJ-projektets webbplats . Hämtad 14 augusti 2016. Arkiverad från originalet 1 maj 2020.
  35. Avvikelser för SML/NJ från definitionen av SML'97 (reviderad) . Hämtad 14 augusti 2016. Arkiverad från originalet 4 april 2016.
  36. SML/NJ: Objektspråksinbäddning med citat/anticitat . Hämtad 14 augusti 2016. Arkiverad från originalet 19 juni 2016.
  37. Slind, "Språkinbäddning i SML/NJ", 1991 .
  38. Poly/ML-projektets webbplats Arkiverad 27 juni 2020 på Wayback Machine
  39. ML Kit-projektets webbplats (otillgänglig länk) . Hämtad 14 augusti 2016. Arkiverad från originalet 19 juli 2016. 
  40. 1 2 Projektera Manticore-webbplatsen . Hämtad 14 augusti 2016. Arkiverad från originalet 8 augusti 2016.
  41. CakeML-projektets webbplats . Hämtad 14 augusti 2016. Arkiverad från originalet 14 september 2020.
  42. sml-evolution konferens: Rober Harper, 10/30/2006.
  43. Shao, "FLINT/ML-kompilator", 1997 .
  44. webbplats för MoscowML-projektet . Hämtad 14 augusti 2016. Arkiverad från originalet 11 januari 2016.
  45. 12 MLton prestanda .
  46. SML.NET projektwebbplats . Hämtad 14 augusti 2016. Arkiverad från originalet 29 januari 2016.
  47. SMLtoJs projektwebbplats (nedlänk) . Hämtad 14 augusti 2016. Arkiverad från originalet 14 september 2016. 
  48. SMLonline-sida (nedlänk) . Hämtad 14 augusti 2016. Arkiverad från originalet 2 oktober 2016. 
  49. sml2c källkoder . Hämtad 14 augusti 2016. Arkiverad från originalet 28 augusti 2018.
  50. Från ML till Ada - beskrivning i MLtons kompilatorguide (nedlänk) . Hämtad 16 september 2016. Arkiverad från originalet 23 september 2016. 
  51. Koser, Larsen, Vaughan, "SML2Java", 2003 .
  52. HaMLet projektplats . Hämtad 14 augusti 2016. Arkiverad från originalet 14 oktober 2016.
  53. Isabelle/ML-projektets webbplats . Hämtad 26 augusti 2016. Arkiverad från originalet 30 augusti 2020.
  54. Poplog-projektets webbplats . Hämtad 26 augusti 2016. Arkiverad från originalet 18 augusti 2016.
  55. Standard ML-projektGitHub
  56. SML# projektwebbplats . Hämtad 14 augusti 2016. Arkiverad från originalet 8 juni 2020.
  57. Mythril projektwebbplats . Hämtad 14 augusti 2016. Arkiverad från originalet 28 juni 2009.
  58. Taha et al, "Macros as Multi-Stage Computations", 2001 .
  59. Pucella, "anteckningar om SML/NJ", 2001 , kapitel 6. Compilation Manager, sid. 157.
  60. eXene - multi-threaded X Window System-verktygssats skriven i ConcurrentML . Hämtad 14 augusti 2016. Arkiverad från originalet 22 februari 2012.
  61. Huelsbergen, "Portable C Interface for SML", 1996 .
  62. Chris Cannam, "Varför var OCaml snabbare?" .
  63. Blume, "No-longer-Foreign", 2001 .
  64. Standard ML Style Guide (från MLton guide) . Hämtad 14 augusti 2016. Arkiverad från originalet 27 augusti 2016.
  65. Appel, "A Critique of Standard ML", 1992 , Felstavade konstruktörer, sid. 12.
  66. Harper, "Intro till SML", 1986 , sid. 5.
  67. "EtaExpansion"-teknik (från MLton Guide) . Hämtad 6 september 2016. Arkiverad från originalet 10 september 2016.
  68. 1 2 Peyton-Jones, "retrospective on Haskell", 2003 .
  69. Typindexerade värden (från MLton Guide) . Hämtad 26 augusti 2016. Arkiverad från originalet 21 april 2016.
  70. "Fold"-teknik (från MLton Guide) . Hämtad 24 augusti 2016. Arkiverad från originalet 26 september 2016.
  71. Shipman, "Unix-programmering med SML", 2001 , s. 31.
  72. Paulson, "ML för den arbetande programmeraren", 1996 , 8.9 Exempel på textbearbetning, sid. 348-350.
  73. 1 2 Paulson, "ML för den arbetande programmeraren", 1996 , 1.5 The efficiency of functional programmering, sid. 9.
  74. 1 2 3 Appel, "A Critique of Standard ML", 1992 .
  75. Paulson, "ML för den arbetande programmeraren", 1996 , sid. 108.
  76. Commentary on SML, 1991 , Aims of the Commentary, sid. vii.
  77. Kommentar till SML, 1991 .
  78. om definitionen av standard ML i MLton guide  (nedlänk)
  79. Kahrs, 1993 .
  80. Kahrs, 1996 .
  81. Defekter i SML (från HaMLet manual) . Hämtad 6 september 2016. Arkiverad från originalet 4 maj 2016.
  82. 12 sml-family.org . _
  83. Paulson, "ML för den arbetande programmeraren", 1996 , 1.9 ML och den arbetande programmeraren, sid. 16.
  84. SML'90, 1990 , sid. v.
  85. SML'90, 1990 , sid. ett.
  86. 1 2 Kommentar till SML, 1991 , sid. 1-3.
  87. Harper-Stone '96, 1996 .
  88. Harper-Stone '97, 1997 .
  89. Harper-Stone '99, 1999 , sid. 1-2.
  90. 1 2 Rossberg, "Defekter i SML Revised", 2001 .
  91. Harper, "Programming in SML", 2005 , 12.1.1 Primitive Exceptions, sid. 104.
  92. Chris Cannam, "Fyra MLs (och en Python)" .
  93. Chlipala, "OCaml vs. SML" .
  94. Olsson, Rossberg, "SML vs. OCaml" .
  95. 1 2 Shaw, "ML vs. Haskell", 2012 .
  96. Dreyer, Harper, "Modular Type Classes", 2007 .
  97. Yallop, White, "Lättviktspolymorfism av högre sort", 2014 .
  98. 1 2 Augustsson, "Mislyckat äventyr i Haskell Abstraktion" .
  99. Wehr, Chakravarty, "Modules vs. Type Classes", 2008 .
  100. Harper, "Naturligtvis har ML monader!" .
  101. Paulson, "ML för den arbetande programmeraren", 1996 , Sequences, or infinite lists, sid. 191-201.
  102. Kommentar till SML, 1991 , 3 Dynamic Semantics for the Modules, sid. 26.
  103. Rossberg, "1ML", 2015 , sid. 2.
  104. Appel, "A Critique of Standard ML", 1992 , Effektivitet, sid. 7-8.
  105. Paulson, "ML för den arbetande programmeraren", 1996 , sid. elva.
  106. MacQueen, "Cardelli and Early Evolution of ML", 2014 , s. fyra.
  107. 1 2 Paulson, "ML för den arbetande programmeraren", 1996 .
  108. Rekommenderade böcker på SML/NJ-kompilatorsidan . Hämtad 26 augusti 2016. Arkiverad från originalet 19 augusti 2016.
  109. Gilmore, "Programmering i SML. Handledningsintroduktion", 1997 , s. 3.
  110. Shipman, "Unix-programmering med SML", 2001 , s. 455.
  111. MacQueen, "Reflections on SML", 1992 , sid. ett.
  112. Pucella, "Anteckningar om SML/NJ", 2001 , sid. 42.
  113. SML-bas på Cambridge University Press-relaterade böcker . Hämtad 19 maj 2022. Arkiverad från originalet 24 februari 2021.
  114. Harper, "Intro till SML", 1986 .
  115. Harper, "Programmering i SML", 2005 .
  116. Gilmore, "Programmering i SML. Handledningsintroduktion", 1997 .
  117. ^ Ullman, "Elements of ML Programming", 1998 .
  118. Shipman, "Unix-programmering med SML", 2001 .
  119. Cumming, 1995 .
  120. Appel, "Modern kompilatorimplementering i ML", 1998 .
  121. Fluet, Pucella, "Phantom Types and Subtyping", 2006 .
  122. Pucella, "Reaktiv programmering i SML", 2004 .
  123. Standard ML-användare . Hämtad 14 augusti 2016. Arkiverad från originalet 10 september 2016.

Litteratur

Standarder

Handledningar, guider, referensböcker, användning

  • Robert Harper Introduktion till Standard ML. - Carnegie Mellon University, 1986. - 97 sid. — ISBN PA 15213-3891.
  • Konrad Slind. Objektspråksinbäddning i Standard ML i New Jersey. - Proceedings of the 2nd ML workshop, Carnegie Mellon University., 1991.
  • Lawrence C. Paulson . ML för den arbetande programmeraren. — 2:a. - Cambridge, Storbritannien: Cambridge University Press, 1996. - 492 s. -ISBN 0-521-57050-6(inbunden), 0-521-56543-X (mjuk pärm).
  • Jeffrey Ullman. Element i ML-  programmering . - Prentice-Hall, 1998. - ISBN 0-13-790387-1 .
  • Andrew W. Appel. Modern kompilatorimplementering i ML  . - Cambridge, Storbritannien: Cambridge University Press, 1998. - 538 s. - ISBN 0-521-58274-1 (inbunden), 0-521-60764-7 (pocket).
  • Anthony L. Shipman. Unix-systemprogrammering med standard  ML . – 2001.
  • Riccardo Pucella. Anmärkningar om programmeringsstandard ML i New  Jersey . - Senast reviderad 10 januari 2001. - Cornell University, 2001.
  • Bernard Berthomieu. OO programmeringsstilar i ML . — LAAS-rapport #2000111, Centre National De La Recherche Scientifique Laboratoire d'Analyse et d'Architecture des Systèmes, 2000.
  • Riccardo R. Pucella. Reaktiv programmering i Standard ML  . — Bell Laboratories, Lucent Technologies, 2004.
  • Matthew Fluet, Riccardo Pucella. Fantomtyper och  undertypning . - JFP , 2006.  - en allmän teknik för att stärka maskinskrivning för tidig upptäckt av fel (se även fulltypsprogrammering )

Historia, analys, kritik

  • Milner , Morris, Newey. En logik för beräkningsbara funktioner med reflexiva och polymorfa typer // Arc-et-Senans. — Proc. Konferens om att bevisa och förbättra program, 1975.
  • Gordon, Milner , Morris, Newey, Wadsworth. Ett metaspråk för interaktivt bevis i LCF. — 1977.
  • David McQueen. Strukturer och parametrering i ett maskinskrivet funktionsspråk. — 1981.
  • Andrew Appel, David MacQueen. Separat kompilering för Standard ML  . - SIGPLAN 94-6/94, ACM 0-89791-662-x/94/006, 1994. - doi : 10.1.1.14.4810 .
  • Stefan Kahrs. Misstag och oklarheter i definitionen av standard ML  -tillägg . - University of Edinburgh, 1996.  (otillgänglig länk)
  • Robert Harper , Christopher A. Stone. En typteoretisk redogörelse för Standard ML // Technical Report CMU-CS-96-136R. — Carnegie Mellon University, 1996.
  • Robert Harper , Christopher A. Stone. En tolkning av Standard ML i typteori // Teknisk rapport CMU-CS-97-147. — Carnegie Mellon University, 1997.
  • Andreas Rossberg, Claudio Russo, Derek Dreyer. F-ing-  moduler . — TLDI, 2010.

Övrigt

  • Derek Dreyer, Robert Harper . Modulära typklasser  . — ACM SIGPLAN, 2007.

Länkar