Standard ML

Den aktuelle version af siden er endnu ikke blevet gennemgået af erfarne bidragydere og kan afvige væsentligt fra den version , der blev gennemgået den 27. februar 2022; checks kræver 3 redigeringer .
Standard ML
Semantik Formel , fortolkningsorienteret
Sprog klasse anvendelig ,
funktionel ,
imperativ
Udførelsestype generelle formål
Dukkede op i 1984 [1] , 1990 [2] , 1997 [3]
Forfatter Robin Milner og andre
Filtypenavn _ .sml
Frigøre Standard ML '97 (1997 ) ( 1997 )
Type system Hindley - Milner
Større implementeringer mange
Dialekter Alice , SML# , Manticore og andre
Blev påvirket Lisp , ISWIM , ML , POP-2 , Hope , Clear [4]
påvirket Erlang , OCaml , Haskell ,
efterfølger ML (sML)
Licens åben kildekode
Internet side sml-family.org
Platform 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 , osv.) ,
Windows , Cygwin , MinGW ,
Darwin , Solaris ,
Hurd , AIX , HP-UX

Standard ML ( SML er et overordnet kompileret programmeringssprog til generelle formålbaseret på Hindley-Milner-systemet .

Det er kendetegnet ved en matematisk præcis definition (som garanterer identiteten af ​​programmernes betydning uanset compiler og hardware), som har en dokumenteret pålidelighed af statisk og dynamisk semantik. Det er et "for det meste funktionelt " sprog [7] [8] , det vil sige, at det understøtter de fleste af de tekniske funktioner i funktionelle sprog, men giver også avancerede imperative programmeringsmuligheder , når det er nødvendigt. Kombinerer stabilitet af programmer, fleksibilitet på niveau med dynamisk indtastede sprog og hastighed på niveau med C -sprog ; giver fremragende support til både hurtig prototyping og modularitet og programmering i stor skala [9] [10] .

SML var det første selvstændige kompilerede sprog i ML -familien og fungerer stadig som ankersproget i ML -udviklingsfællesskabet ( efterfølger ML ) [11] . SML var den første til at implementere et unikt applikativt modulsystem  , ML-modulsproget .

Generel information

Sproget er oprindeligt fokuseret på storskala programmering af softwaresystemer: det giver effektive midler til abstraktion og modularitet , hvilket giver en høj kodegenbrugshastighed , og dette gør det også velegnet til hurtig prototyping af programmer, herunder storskala . For eksempel, under udviklingen af ​​den (dengang stadig eksperimentelle) SML/NJ-kompiler ( 60 tusind linjer pr. SML), var det nogle gange nødvendigt at foretage radikale ændringer i implementeringen af ​​nøgledatastrukturer, der påvirker snesevis af moduler - og den nye version af compileren blev klar i løbet af dagen. [9] (Se også ICFP Programming Contest 2008, 2009.) Men i modsætning til mange andre sprog, der er egnede til hurtig prototyping , kan SML kompilere meget effektivt .

SML er kendt for sin relativt lave adgangstærskel og fungerer som undervisningssprog i programmering på mange universiteter rundt om i verden [12] . Det er omfattende dokumenteret i arbejdsform og bruges aktivt af videnskabsmænd som grundlag for at forske i nye elementer i programmeringssprog og idiomer (se f.eks. polymorfi af strukturelle typer ). På nuværende tidspunkt er alle implementeringer af sproget (inklusive forældede) blevet open source og gratis .

Karakteristiske træk

Sproget har en matematisk præcis ( eng.  rigorous ) formel definition kaldet "Definition" ( eng. The Definition ). Til definitionen er der bygget en fuld type sikkerhedsbevis , som garanterer stabiliteten af ​​programmer og forudsigelig adfærd selv med forkerte inputdata og mulige programmeringsfejl. Selv et buggy SML-program opfører sig altid som et ML-program: det kan gå i beregning for evigt eller kaste en undtagelse , men det kan ikke gå ned [13] .  

SML er et for det meste funktionelt ( for det meste funktionelt eller primært funktionelt ) sprog [7] [8] , det vil sige, at det understøtter de fleste af de tekniske funktioner i funktionelle sprog, men giver også imperative programmeringsmuligheder . Det er mere almindeligt omtalt som et " højere ordens sprog for at understrege støtte til førsteklasses funktioner, mens det stadig adskiller det fra referentielt gennemsigtige sprog .

SML giver enestående support til programmering i stor skala gennem det mest kraftfulde og udtryksfulde modulsystem kendt ( ML Module Language ). SML implementerer en tidlig version af modulsproget, som er et separat lag af sproget: moduler kan indeholde kernesprogobjekter, men ikke omvendt [14] .

I modsætning til mange andre sprog i ML -familien ( OCaml , Haskell , F# , Felix, Opa, Nemerle og andre), er SML meget minimalistisk: det har ikke indfødt objektorienteret programmering , samtidighed , ad-hoc polymorfi , dynamisk skrivning , listegeneratorer og mange andre funktioner. SML er dog ortogonal [15] (det vil sige, at den implementerer det mindst nødvendige, men det fulde sæt af maksimalt forskellige elementer), hvilket gør det relativt nemt at efterligne andre funktioner, og de nødvendige teknikker er dækket bredt i litteraturen . Faktisk giver SML dig mulighed for at bruge vilkårlig funktionalitet på højt niveau som en primitiv til at implementere funktionalitet på endnu højere niveau [16] . Især er implementeringsmodeller af typeklasser og monader bygget ved hjælp af kun standard SML-konstruktioner, samt objektorienterede programmeringsværktøjer [17] . Desuden er SML et af de få sprog, der direkte implementerer førsteklasses fortsættelser .

Funktioner

Kraftfuldt udtryksfuldt typesystem

Hindley-Milner (X-M)-systemet er et karakteristisk træk ved ML og dets efterkommere. Det sikrer programmernes pålidelighed på grund af tidlig detektering af fejl, høj kodegenbrug , høj potentiale for optimering , kombinerer disse kvaliteter med kortfattethed og udtryksfuldhed på niveauet af dynamisk indtastede sprog. De mest fremtrædende egenskaber, der er iboende i X-M, er type polymorfi , såvel som algebraiske datatyper og mønstermatchning på dem.

Implementeringen af ​​X-M i SML har følgende funktioner:

Support til funktionel programmering Understøttelse af tvingende programmering Sikring af høj programeffektivitet

Brug

I modsætning til mange sprog giver SML en lang række måder at bruge det på [21] :

På samme tid, i visse tilstande, er en række forskellige målplatforme og kompileringsstrategier mulige :

Selve kompileringsstrategierne adskiller sig også væsentligt:

Sprog

Grundlæggende semantik

Deklarationer, udtryk, blokke, funktioner Primitive typer Sammensatte og definerede typer Foranderlige værdier Begrænsning af værdier

Værdibegrænsning _ _  _ _

Kontrolstrukturer

Programmering i stor skala

Modularitet

SML - modulsystemet er det mest udviklede modulsystem inden for programmeringssprog. Det gentager semantikken i kerne-ML ( eng.  Core ML ), således at afhængigheder mellem store programkomponenter bygges som afhængigheder på et lille niveau. Dette system af moduler består af tre typer moduler:

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

Strukturer ligner moduler i de fleste programmeringssprog. Signaturer tjener som strukturgrænseflader, men er ikke stift bundet til bestemte strukturer, men bygger relationer i henhold til " mange-til-mange " -skemaet , hvilket giver dig mulighed for fleksibelt at kontrollere synligheden af ​​strukturkomponenter afhængigt af behovene i programkonteksten.

Funktioner er " funktioner over strukturer ", som giver dig mulighed for at bryde kompileringstidsafhængigheder og beskrive parameteriserede moduler. De gør det muligt at skrive -sikkert beskrive beregninger på programkomponenter, der på andre sprog kun kan implementeres gennem metaprogrammering [23]  - som C++ skabeloner , kun uden smerte og lidelse [24] , eller Lisp makrosproget , kun med statisk sikkerhedskontrol af den genererede kode [23] . De fleste sprog har slet ikke noget, der kan sammenlignes med funktioner [25] .

Den grundlæggende forskel mellem ML-modulsproget er, at resultatet af en funktor ikke kun kan indeholde værdier, men også typer, og de kan afhænge af de typer, der er en del af funktorparameteren. Dette gør ML-moduler nærmest i deres udtryksevne til systemer med afhængige typer , men i modsætning til sidstnævnte kan ML-moduler reduceres til et fladt System F ω (se Modulsprog ML#F-Rossberg-Rousseau-Dreyer ).

Syntaks og syntaktisk sukker

Sprogets syntaks er meget kort, med hensyn til antallet af reserverede ord indtager det en mellemposition mellem Haskell og Pascal [26] .

SML har en kontekstfri grammatik , selvom der er nogle uklarheder i den. SML/NJ bruger LALR(1) , men LALR(2) findes ét sted.

Liste over sprogsøgeord ( identifikatorer , der matcher dem , er ikke tilladt) [27] :

abstype og og også som case datatype do else end eqtype undtagelse fn fun functor handle if in include infix infixr lad local nonfix of op open orelse raise rec deling signatur struct struktur skriv val hvor mens med withtype

Tegnidentifikatorer er også tilladt - det vil sige, type-, data- og funktionsnavne kan bestå af følgende ikke-alfabetiske tegn:

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

Navnene på disse symboler kan have en hvilken som helst længde [27] :

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

Selvfølgelig er brugen af ​​sådanne navne i praksis ikke ønskelig, men hvis den tidligere forfatter af den vedligeholdte kode brugte dem i vid udstrækning, så bliver det muligt takket være den formelle definition (og SML selv gør det ret nemt at løse dette problem) skrive en præprocessor til at rette hukommelsestegn.

Kun følgende tegnstrenge er udelukket:

: | ==> -> # :>

Årsagen til denne begrænsning ligger i deres særlige rolle i sprogets syntaks:

: - eksplicit værditype annotation _ | - adskillelse af prøver = - adskille funktionslegemet fra dets overskrift => - at adskille lambdafunktionens krop fra dens header -> — konstruktør af funktionel (pile) type # - adgang til registreringsfeltet :> - at matche strukturen med signaturen

SML har ingen indbygget syntaks for arrays og vektorer (konstante arrays). Nogle implementeringer understøtter til en vis grad syntaksen for arrays ( [|1,2,3|]) og vektorer ( ) #[1,2,3]som en udvidelse.

Opgaveoperationen er skrevet som på Pascal -sprog :x:=5

Sprogøkosystem

Standardbibliotek

SML - standardbiblioteket hedder Basis .  Det har udviklet sig over mange år efter at have gennemgået strenge tests på reelle problemer baseret på SML/NJ , dets udkast blev offentliggjort i 1996 [28] , og derefter blev dets specifikation officielt offentliggjort i 2004 [29] . I denne periode udkom der allerede manualer til dets brug [30] . Basisbiblioteket implementerer kun det nødvendige minimum af moduler: trivielle datatyper, aritmetik over dem, input-output , platformsuafhængig grænseflade til operativsystemet osv., men implementerer ikke mere kompleks funktionalitet (for eksempel multithreading). Mange compilere giver desuden forskellige eksperimentelle biblioteker.

Kompilere kan bruge viden om Basis til at anvende præ-optimerede algoritmer og specialiserede optimeringsteknikker: MLton bruger f.eks. den native repræsentation af Basis-typer (svarende nøjagtigt til primitive C -sprogtyper ) samt de enkleste aggregerede typer, der består af dem.

Som med de fleste sprog har SML Basis en række specifikke arkitektoniske og syntaktiske konventioner. Først og fremmest er disse trivielle komponenter i standardstrukturer, såsom kombinatorer, der ligner navn og signaturer (såsom fold). Yderligere er dette et skema, der gælder for de fleste typer konvertering til strengtype og omvendt .

Konvertere og scannere

Standardskemaet for konvertering til og fra en strengtype er indkapslet i en struct StringCvt:

struktur StringCvt : sig datatype radix = BIN | okt | DEC | HEX datatype realfmt = SCI af int option | FIX af int option | GEN af int option | PRÆCIS type ( 'a , 'b ) reader = 'b -> ( 'a * 'b ) mulighed val padVenstre : char -> int -> streng -> streng val padHøjre : char -> int -> streng -> streng 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 type cs val scanString : (( char , cs ) reader -> ( 'a , cs ) reader ) -> string -> 'a option end

Konverteringsskemaet er ikke begrænset til at opstille baser af talsystemer, som i C ( BIN, OCT, DEC, HEX). Det strækker sig til højere ordens programmering , hvilket giver dig mulighed for at beskrive operationerne ved at læse værdier af specifikke typer fra abstrakte strømme og skrive til dem, og derefter transformere simple operationer til mere komplekse ved hjælp af kombinatorer . Streams kan være standard I/O- streams eller blot aggregerede typer såsom lister eller strenge. [31]

Læsere, det vil sige værdier af typen ('a,'b) reader. Intuitivt er en læser en funktion, der tager en strøm af type som input 'bog forsøger at læse en værdi af type fra den 'a, og returnerer enten den læste værdi og "resten" af strømmen, eller NONEhvis den fejler. En vigtig type læsere er scannere eller scanningsfunktioner. For en given type har Tscanningsfunktionen typen

( char , 'b ) læser -> ( T , 'b ) læser

- det vil sige, at det er en konverter fra en karakterlæser til en læser af denne type. Scannere er inkluderet i mange standardmoduler, for eksempel INTEGERinkluderer signaturen en scanner for heltal:

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

Tal læses atomært, men læsere kan læse fra strømme og kæder element for element, for eksempel tegn for tegn en linje fra en streng:

fun stringGetc ( s ) = lad val ss = Understreng . fulde ( r ) i tilfælde af Substring . getc ( ss ) af INGEN => INGEN | SOME ( c , ss' ) => SOME ( c , Understreng . streng ( ss' )) ende ; stringGetc ( "hej" ); (* val it = SOME (#"h","ello") : (char * string) option *) stringGetc ( #2 ( valOf it ) ); (* val it = SOME (#"e","llo") : (char * string) option *) stringGetc ( #2 ( valOf it ) ); (* val it = SOME (#"l","lo") : (char * string) option *) stringGetc ( #2 ( valOf it ) ); (* val it = SOME (#"l","o") : (char * string) option *) stringGetc ( #2 ( valOf it ) ); (* val it = SOME (#"o","") : (char * string) option *) stringGetc ( #2 ( valOf it ) ); (* val it = INGEN : (char * streng) mulighed *)

Scannere giver dig mulighed for at oprette læsere fra eksisterende læsere, for eksempel:

val stringGetInt = Int . scan StringCvt . DEC -strengHent

Strukturen StringCvtgiver også en række hjælpefunktioner. For eksempel, splitlog takelkombiner dropltegnlæsere med tegnprædikater for at tillade, at streams kan filtreres.

Det skal bemærkes, at ikke karakterlæsere er et særligt tilfælde af læsere generelt, men omvendt [32] . Grunden til dette er, at udtrækning af en undersekvens fra en sekvens er en generalisering af at udtrække en understreng fra en streng.

Portering

definitionen ret strengt . Forskellene ligger i tekniske detaljer, såsom det binære format af separat kompilerede moduler, implementeringen af ​​FFI osv. I praksis skal et rigtigt program starte fra et bestemt grundlag (et minimumssæt af typer, input-output faciliteter , etc.). Definitionen stiller dog kun minimale krav til sammensætningen af ​​det oprindelige grundlag, så det eneste observerbare resultat af et korrekt program ifølge definitionen er, at programmet afslutter eller afgiver en undtagelse, og de fleste implementeringer er kompatible på dette niveau [33] .

Selv standarden Basis har dog nogle potentielle problemer med overførsel. For eksempel [33] indeholder en konstant værdien af ​​det størst mulige heltal, pakket ind i den valgfri type , og skal hentes enten ved mønstermatchning eller ved et funktionskald . For finite dimensionstyper er værdien , og begge ekstraktionsmetoder er ækvivalente. Men er lig , så adgang til indholdet direkte via vil give en undtagelse . Åbnet som standard , for eksempel i Poly/ML -kompileren . Int.maxIntvalOfIntN.maxIntSOME(m)IntInf.maxIntNONEvalOf OptionIntInf

Med en vis indsats er det muligt at udvikle programmer, der er frit bærbare mellem alle aktuelle implementeringer af sproget. Et eksempel på et sådant program er HaMLet .

Udviklingsværktøj

Til dato er Standard ML blevet fuldstændig offentligt: ​​alle implementeringer er gratis og open source og distribueres under de mest loyale licenser ( BSD-stil , MIT ); teksterne til Sprogdefinitionen (både i 1990-versionen og den reviderede 1997-version) og Basisspecifikationen er også tilgængelige gratis .

SML har et stort antal implementeringer. En betydelig del af dem er skrevet i selve SML; undtagelserne er kørselstiderne for nogle kompilatorer skrevet i C og Assembler , såvel som Poplog systemet .

Kompilere til native kode
  • SML/NJ (Standard ML of New Jersey) ( hovedartikel ) [34] er en optimeringskompiler på tværs af platforme. Understøtter REPL og batch-kompilering. Er den "kanoniske" implementering af SML, selvom den har mange afvigelser fra definitionen [35] ; fungerede som et udviklingsværktøj for en række andre compilere og automatiske korrektursystemer . Genererer indbygget kode til et stort antal arkitekturer og operativsystemer. FFI er baseret på dynamisk kodegenerering. Giver en række eksperimentelle udvidelser, hvoraf de mest bemærkelsesværdige inkluderer støtte til førsteklasses fortsættelser , en implementering af CML baseret på dem, en af ​​implementeringerne af højere-ordens (men ikke førsteklasses ) moduler, og en kvasi -citatmekanisme til indlejring af sprog [36] [37] . Ledsaget af rig dokumentation.
  • MLton (udtales " milton ") ( hovedartikel ) ( projektwebsted ) er en kompilator til optimering af hele programmet på tværs af platforme . Giver C / C++- niveau ydeevne til SML-programmer gennem aggressive optimeringer, herunder udvidelse af modulomfang, fuld programmonomorfisering og defunktionalisering og indbygget (uindpakket og ikke-lagret) repræsentation af primitive typer, strenge og arrays; har direkte FFI ; til lange aritmetiske bruger GnuMP . Genererer indbygget kode for et stort antal arkitekturer under Unix-lignende OS (under Windows kræver Cygwin eller MinGW ); har back-ends i C , C-- , LLVM . Indeholder det komplette kernebibliotek (selv alle valgfrie strukturer), har sine egne porte til mange af de typiske SML/NJ- biblioteker , inklusive implementering af fortsættelser og CML . FFI giver opkald i begge retninger ( C -funktioner fra SML-kode og omvendt), op til gensidig rekursion . Den er ledsaget af meget rig dokumentation, herunder en beskrivelse af tricks med ikke-triviel brug af sproget, så det kan udvides med nyttige idiomer . Ulemperne på grund af global analyse og mange transformationstrin er betydelige tids- og hukommelsesomkostninger til arbejde.
  • Poly/ML [38] er en optimeringskompiler på tværs af platforme. Genererer en ret hurtig kode, understøtter multiprocessorsystemer (på POSIX-tråde ), udfører parallel affaldsopsamling og sikrer sambrug af uforanderlige datastrukturer; bruger lang aritmetik som standard (en struktur er knyttet til signaturen INTEGERpå øverste niveau IntInf). Giver en direkte grænseflade til WinAPI og X Window System . Den binære implementering kommer under Windows ; under andre operativsystemer skal du selv indsamle kildekoderne. Genererer indbygget kode til i386 , PowerPC , SPARC , har back-end til bytekode til at køre på ikke-understøttede platforme. Poly/ML er kernen i Isabelle (automatiseret teorembevissystem) sammen med SML/NJ .
  • ML Kit [39] er en fuld-optimerende compiler. Fokuseret på applikationsudvikling i realtid : bruger en hukommelsesstyringsstrategi baseret på statisk regioninferens , hvilket tillader konstant tidsindsamling af skrald ; samt den ikke-standardiserede mulighed for midlertidigt at slukke for skraldesamleren omkring hastighedskritiske sektioner. Udvider omfanget af moduler - udover at forbedre ydeevnen er dette også vigtigt for at vise regioner. Giver en ret høj ydeevne programmer. Genererer native x86 -kode til Windows og Unix , har også backends til bytekode og JavaScript -kode . Blandt manglerne kan man notere manglen på støtte til samtidighed og ensrettethed af FFI (opkald fra SML til C leveres, men ikke omvendt).
  • SML# (ikke at forveksle med SML.NET ) er en optimerende SML-kompiler med udvidelser (danner SML# dialekten ). Navnet bør ikke være vildledende, SML# kompilerer til native kode og er ikke relateret til .NET platformen (SML# dukkede op flere år tidligere). Genererer native x86 -kode under POSIX . Startende med version 2.0 er back-end baseret på LLVM , som yderligere vil udvide listen over understøttede arkitekturer. Version 3.0 introducerede x86-64 -understøttelse og en fuldt samtidig affaldsopsamler for at sikre effektiv brug af multi-core-systemer og ingen programpauser. Giver god ydeevne, herunder på grund af den native (uindpakkede og umærkede) repræsentation af primitive typer og direkte FFI til C og SQL ; stærkere optimeringer er planlagt i den nærmeste fremtid. Indeholder også en smuk printgenerator , en dokumentationsgenerator.
  • Manticore [40] er en compiler til Manticore dialekten . Genererer native x86-64 kode til Linux og MacOS X. Fungerer i REPL -tilstand .

Verifikation af compilere
  • CakeML [41] er en dokumenteret pålidelig compiler . Implementerer en betydelig delmængde af Standard ML og er selvskrevet (inklusive runtime ). Både sprogets semantik og kompileringsalgoritmen er beskrevet af højere ordens logik og verificeret , så CakeML-programmer oversættes til semantisk ækvivalent maskinkode med dokumenteret pålidelighed . Målet med projektet er at gøre interaktive bevissystemer til en praktisk platform for anvendt udvikling. For 2016 genererer den native kode til x86-64 , understøttelse af en række andre arkitekturer er planlagt i den nærmeste fremtid.
  • TILT , eller TIL-Two ( kildekoder (Git) ) er en compiler baseret på ideen om udelukkende at bruge typesikre mellemsprog​ i kompileringsprocessen ( Typed Intermediate Language , TIL - deraf navnet), op til maskinskrevet assembler , for at opretholde sikkerhedsprogrammer på alle stadier af transformation og optimering. Forsiden af ​​compileren er baseret på Harper-Stone semantik [42] . Udviklet af Robert Harper og kolleger til forskningsformål i midten af ​​1990'erne og er ikke blevet vedligeholdt siden.
  • FLINT ( projektside på Yale.edu ) ligner TILT , men det interne sprog har ikke en dedikeret modulregning, mens det eksterne sprog understøtter højere-ordens moduler. FLINT blev introduceret i SML/NJ, hvilket øgede sidstnævntes ydeevne. [43]

Kompilere til bytekoder og Java
  • Alice er en cross-platform SML compiler med udvidelser (danner Alice dialekten ) til JIT VM bytecode . Fokus på udvikling af distribuerede systemer . Den har sin egen REPL - IDE med en indbygget inspektør, som gør det muligt at kompilere udvalgte kodefragmenter (forudsat at de er selvforsynende) og derefter giver interaktiv information om de afledte typer. Separat kompilering understøttes. Fungerer under Windows og forskellige Unix-lignende systemer. Ud over standard Basis giver den en række ekstra biblioteker, har en grænseflade til SQLite og Gtk+ . Ledsaget af detaljerede instruktioner til brug af det medfølgende sprog og biblioteksudvidelser (forudsat kendskab til SML).
  • Moscow ML [44] er en let compiler til bytekode . Baseret på Caml Light runtime , understøtter REPL og batch kompilering. Kompilerer hurtigt, men optimeringen er ubetydelig [45] . Giver sprogudvidelser ( funktioner af højere orden , pakker , quasi-citering grænseflade til en række system- og multimediebiblioteker. Udviklet i RuslandKeldysh Institute under vejledning af Romanenko A.S. til uddannelsesformål; understøttelse af sproget for moduler med udvidelser blev implementeret af Claudio Russo (forfatter af pakkesemantik ).
  • MLj - se SML.NET
  • SML.NET [46] - må ikke forveksles med SML# - fuldoptimerende compiler til .Net -platformen . Det voksede ud af MLj- kompileren til JVM -platformen . Giver en grænseflade til at forbinde med andre .NET -sprog. Det har sit eget afhængighedsanalysesystem mellem moduler. Kompilerer kun hele moduler, udvider deres omfang. Styres både fra den normale kommandolinje og fra den oprindelige REPL -tilstand .
  • SMLtoJs [47] er en compiler til JavaScript -kildekode . Udfører flere optimeringer, herunder afsløring af omfanget af moduler. Den bruger MLton og ML Kit til at fungere .
    • SMLonline [48] er en online IDE til SMLtoJ'er , der giver dig mulighed for at arbejde eksternt fra en browser .
  • sml2c [49] er en compiler til C- kildekode . Bygget oven på SML/NJ frontend og runtime , og understøtter mange af dens udvidelser (inklusive førsteklasses fortsættelser ). Genererer kode i bærbar ANSI C , men på grund af forskelle i semantiske egenskaber giver det en 70-100 % opbremsning sammenlignet med direkte oversættelse af SML til maskinkode [5] . Fungerer kun med definitioner på modulniveau i batch-tilstand. Programmer på modulniveau kompileret med SML/NJ kan kompileres med SML2c uden ændringer. I modsætning til SML/NJ understøtter den ikke fejlretning og profilering på kildekodeniveau.
  • RML-to-3GL er en compiler af RML-sproget (en delmængde af den fjerde generations sprog SML) til kildekode i Ada ( tredje generations type sikkert sprog) [6] . Det ligner i strukturen MLton [50] : det bruger monomorfisering , defunktionalisering , og udfladning af et højere-ordens sprog til et første-ordens sprog.
  • SML2Java er en compiler til Java -kildekode [51] .

Implementeringer på højere niveau
  • HaMLet [52] er referenceimplementeringen af ​​SML. Repræsenterer en tolk til en direkte, linje-for-linje, implementering af Definition sproget. Ikke beregnet til industriel brug - meget ineffektiv og giver få informative fejlmeddelelser - i stedet tjener det som en platform for forskning i selve sproget og leder efter mulige fejl i definitionen. Selve HaMLet er skrevet udelukkende i SML (25k linjer kode) uden brug af C , og nogle SML-kompileres evne til at samle HaMLet-koder kan ses som et tegn på en rimelig god implementering af sprogdefinitionen og kernebiblioteket. Især er HaMLet-koder i stand til at kompilere SML/NJ , MLton , Moscow ML , Poly/ML , Alice , ML Kit , SML# , og selvfølgelig ham selv. HaMLet har også en " HamLet S "-tilstand, som er referenceimplementeringen af ​​den nuværende version af efterfølgeren ML (sML) . Designet og vedligeholdt af Andreas Rossberg.
  • Isabelle/ML [53] er en LCF - stil komponent af Isabelle ( sætningsbevissystem ) . Isabelle blev udviklet under ledelse af Luca Cardelli baseret på HOL-90- systemet . Indeholder en editor baseret på jEdit . Den væsentligste komponent i Isabelle er Isabelle/HOL , som baseret på eksekverbare specifikationer giver dig mulighed for at generere SML, OCaml , Haskell , Scala kildekoder samt dokumentation baseret på L A Τ Ε Χ indsættelser i kildekoden.
  • Edinburgh LCF (Logic for Computable Functions) ( hovedartikel ) (kildekoder er tilgængelige som en del af Isabelle ) - et interaktivt teorembevissystem , historisk set den første implementering af ML-rodsproget (før introduktionen af ​​modulsproget og dannelsen af ​​SML).

Forældede implementeringer
  • Poplog [54] er en inkrementel compiler og integreret udviklingsmiljø fokuseret på at arbejde inden for kunstig intelligens . Giver mulighed for at blande flere sprog på samme tid, inklusive POP-11 , Prolog , Common Lisp og SML. Den interne repræsentation af alle sprog er baseret på POP-11 - Lispo - lignende reflekterende sprog; Poplog selv er implementeret på den. Indeholder en Emacs -lignende editor og GUI- understøttelse, men kun under X Window System ; under Windows giver det kun en konsol. Navnet Poplog er et akronym for "POP-11" og "Prolog". På trods af det faktum, at Poplog er aktivt udviklet, har det haltet bagefter udviklingen af ​​SML-sproget: i øjeblikket overholder dets SML-implementering ikke den nuværende Definition ( SML'97 ) og implementerer ikke Core Library.
  • MLWorks [55] er en compiler med en komplet IDE og relaterede værktøjer. Tidligere kommerciel, udviklet af Harlequin i 1990'erne . Ved århundredeskiftet skiftede ejeren, og støtten blev indstillet. I 2013 fandt han en ny ejer, som åbnede kildekoderne og organiserede arbejdet med genoplivning af projektet. Ikke operationelt i 2016 .
  • Edinburgh ML ( kildekoder ) er en ML-compiler, der ikke er snoet , baseret den historisk første ML -compiler udviklet af Luca Cardelli Vax ML (den anden implementering af ML efter Edinburgh LCF (Logic for Computable Functions) ). Koderne er nu open source, men da de ikke har ændret sig siden 1980'erne , siger de stadig, at ML ikke er i det offentlige domæne, og brugen af ​​denne compiler kræver licens.
  • TILT - se Bekræftelse af kompilatorer

Dialekter, udvidelser

SML#

SML# [56] udvider konservativt SML med rekordpolymorfi i Atsushi Ohori-modellen , som SML# bruger til problemfrit at indlejre SQL i SML-kode til intensiv databaseprogrammering.

Pundsymbolet ( #) i sprognavnet symboliserer vælgeren (handlingen med at vælge et felt fra en post). Compileren af ​​samme navn hævder god ydeevne. Udviklet og udviklet på Tohoku Institute (Japan) under vejledning af Ohori selv.

Alice

Alice ML udvider konservativt SML med primitiver for samtidig programmering baseret på den eksotiske" opkald af fremtidig " evalueringsstrategi , begrænsningsløseren og alle de konsistente elementer i det efterfølgende ML- design . Især Alice understøtter førsteklasses moduler i form af pakker med dynamisk indlæsning og dynamisk typing , som tillader implementering af distribueret computing . Alice giver også futures førsteklasses egenskaber, herunder leverer futures på modulniveau ( fremtidige strukturer og fremtidige signaturer). Compileren bruger en virtuel maskine. Udviklet og udviklet på Saarland University under ledelse af Andreas Rossberg.

Samtidig ML

Concurrent ML (CML) et integreret sprogbibliotek, derudvider SML med højere ordens samtidige programmeringskonstruktioner baseret på densynkroneførsteklassesmeddelelsesmodel. Inkluderet i standarddistributionen af ​​SML/NJ ogMLton-kompilatorerne. Kerneideerne i CML er kernen i Manticore -projektet og er indarbejdet i det efterfølgende ML -projekt [11] .

Manticore

Manticore [40] implementerer omfattende support til samtidig og parallel programmering, fra den logiske nedbrydning af et system til processer til finkornet kontrol over den mest effektive brug af multi-core systemer . Manticore er baseret på en delmængde af SML, eksklusive mutable arrays og referencer, dvs. det er et rent sprog, der opretholder en streng evalueringsrækkefølge . Eksplicitte samtidigheds- og grove parallelismemekanismer ( tråde ) er baseret på CML , mens fine datalags - parallelismemekanismer (parallelle arrays ) ligner NESL . Compileren af ​​samme navn genererer indbygget kode .

MLPolyR

MLPolyR  er et legetøjssprog, der er baseret på en simpel delmængde af SML og tilføjer flere niveauer af typesikkerhed til det . Målet med projektet er at uddybe studiet af rekordpolymorfi til behovene i det efterfølgende ML -projekt . Det innovative MLPolyR - system løser -udtryksproblemet og garanterer ingen ubehandlede undtagelser i programmer.

Udviklet under ledelse af Matthias Blum (forfatter af NLFFI ) ved Toyota Institute of Technology i Chicago , USA .

Mythryl

Mythryl [57]  er en syntaksvariant af SML, der har til formål at fremskynde POSIX- udviklingen . Den nye syntaks er stærkt lånt fra C; terminologien er også blevet revideret til at være mere traditionel (f.eks. er funktorer blevet omdøbt til generiske ). Samtidig understreger forfatterne, at de ikke har til hensigt at skabe "endnu et dump af sprogtræk", men holder sig til SML's minimalistiske karakter og stoler på dens definition . Implementeringen er en forgrening af SML/NJ .

Andre

Hjælpeprogrammer

  • Compilation Manager (CM) og MLBasis System (MLB)  er kompileringsudvidelser for bedre at understøtte modularitet (afhængighedskontrol). I princippet kunne make , traditionel for de fleste sprog, også bruges til dette formål , men SML-modulsproget er meget mere kraftfuldt end modulariseringsværktøjerne på andre sprog, og make understøtter ikke dets fordele og er ikke egnet til at arbejde i REPL -tilstand [59] . CM blev oprindeligt implementeret i SML/NJ , derefter porteret til MLton . Senere, som en del af MLton , blev MLB-systemet og .cm til .mlb -filkonverteren foreslået . MLB-understøttelse er blevet tilføjet til ML-kittet .
  • eXene [60] er et GUI-  bibliotek til X Window System . Implementerer en reaktiv interaktionsmodel baseret på CML . Leveres med SML/NJ .
  • MLLex , MLYacc , MLAntlr , MLLPT er lexer- og parser  -generatorer (se Lex og Yacc ).

Interlingual interaktion

  • FFI (Foreign Function Interface -Russisk grænseflade til fremmede funktioner) - tværsproglige bindinger . I forskellige compilere har den en anden implementering, som er tæt forbundet med datarepræsentationen (først og fremmest pakket ind eller ud, tagget eller ukodet). I SML/NJ er FFI baseret på dynamisk kodegenerering, og hvis en funktion tager i alt bytes som inputnog returnerermen byte, så har dens kaldkompleksitet n+m [61] . Nogle compilere (MLton ,SML# ) bruger uindpakket og tagløs datarepræsentation og giver direkte opkald til C-funktioner og data. I sidstnævnte tilfælde kan indsættelse af langsomme funktioner i C-kode øge programmets overordnede ydeevne betydeligt [62] .
  • NLFFI (No-Longer-Foreign Function Interface - Russisk grænseflade til nu-ikke-mere-udenlandske funktioner ) [63]  - en alternativ grænseflade på højere niveau af eksterne funktioner . NLFFI genererer automatisk limkode, hvilket tillader *.h-filer ( C - header-filer ) at blive inkluderet direkte i et SML-projekt (CM eller MLB ), hvilket eliminerer behovet for manuel kodning af FFI -definitioner . Strukturelt er ideen med NLFFI at modellere C -typesystemet med ML-typer; implementeringen er baseret på CKit . Leveres med SML/NJ og MLton .
  • CKit  er et front-end C -sprog skrevet i SML. Udfører oversættelse af C-kildekoder (inklusive præprocessor) til AST , implementeret ved hjælp af SML-datastrukturer. Ligger til grund for implementeringen af ​​NLFFI .

Ideomatik, konventioner

Der er ingen krav til design af programmer i SML, da sprogets grammatik er fuldstændig kontekstfri og ikke indeholder åbenlyse uklarheder. Den bemærker dog særlige problemer, for eksempel, når man passerer multiplikationsoperatoren, skal den op *afsluttende parentes adskilles med et mellemrum ( (op * )), da når de skrives i kontinuerlig form, tager mange implementeringer (ikke alle) et par tegn *)for at lukke en kommentar i koden og generere en fejl.

Der er dog stadig visse anbefalinger, der sigter mod at forbedre læsbarheden, modulariteten og genbrug af kode, samt tidlig opdagelse af fejl og øge modificerbarheden (men ikke til at indtaste oplysninger om typer i identifikatorer, som det f.eks. gøres i ungarsk notation ) [ 64] . SML anbefaler især en navnekonvention for kerneniveauidentifikatorer svarende til den, der kræves af Haskell : fooBarfor værdier, foo_barfor typekonstruktører , FooBarfor konstruktørfunktioner (nogle kompilatorer udsender endda en advarsel, hvis den overtrædes). Dette skyldes karakteren af ​​mønstermatching, som generelt ikke er i stand til at skelne mellem lokal variabel input og nul- type konstruktørbrug , så stavefejl kan føre til (relativt let opdagelige) fejl [65] .

Det mest usædvanlige og uventede kan være:

  • præference for et indrykningstrin på tre tegn (ikke fire)
  • hyppig brug af apostrof i identifikatorer (svarende til det, der er vedtaget i matematik): hvis du xvil bygge et " nyt x " på grundlag, så skriver de på de fleste sprog " x1", og i SML, som i matematik, ofte “ x'” (“ x-slag ”).
  • syntaks for binære logiske operationer "AND" og "OR": andalsoog orelsehhv. [66]
  • syntaks for infix-streng og listesammenkædningsoperationer: ^og @henholdsvis (ikke angivet for vektorer og arrays).
Procedurer

For procedurer anvendes det samme formsprog som i C : procedurer er repræsenteret af funktioner, der returnerer en værdi af en enkelt type :

sjov p s = print s (* val p = fn : sting -> enhed *) Sekventiel databehandling lad D i E ende sjov foo ... = lad val _ = ... i ... ende

Teknikker

Denne -udvidelse

Dette -expansion ( engelsk  eta-expansion ) udtrykeer et udtrykfn z => e z, det vil sige en indpakning af det oprindelige udtryk til en lambda-funktion , hvorzdet ikke forekommer ie. Dette giver selvfølgelig kun mening, hvisedet har en piltype , det vil sige, det er en funktion. Denne -udvidelse tvinger evalueringen til at blive forsinket,eindtil funktionen anvendes, og til at blive revurderet, hver gang den anvendes. Denne teknik bruges i SML til at overvinde de ekspressivitetsbegrænsninger, der er forbundet med semantikken værdibegrænsningen . Udtrykket " eta -ekspansion" er lånt fra eta -transformationen i lambda calculus , der tværtimod betyder reduktionen af ​​et udtryktil,hvis detikke forekommer i( eta -kontraktion). [67] [68]fn z => e zeze

Værdier indekseret efter typer

Værdier indekseret efter typer ( engelsk  typeindekserede værdier ) er en teknik, der giver dig mulighed for at introducere understøttelse af ad-hoc polymorfi i SML (som den i første omgang mangler) [69] . Der er en række af dens varianter, herunder dem, der har til formål at understøtte fuldgyldig objektorienteret programmering [17] .

Fold

" Fold " [70]  er en teknik, der introducerer en række almindelige idiomer i SML, herunder variadiske funktioner, navngivne funktionsparametre, standardparameterværdier, syntaktisk understøttelse af arrays i kode, funktionel opdatering af poster og en kosmetisk repræsentation af afhængig indtastning at give typesikkerhed af funktioner som printf.

Princip

Det er nødvendigt at definere tre funktioner - fold, step0og $- sådan at følgende lighed er sand:

fold ( a , f ) ( step0 h1 ) ( step0 h2 ) ... ( step0 hn ) $ = f ( hn (... ( h2 ( h1 a ))))

Deres minimale definition er lakonisk:

sjov $ ( a , f ) = f a struktur Fold = struktur sjov fold ( a , f ) g = g ( a , f ) sjov step0 h ( a , f ) = fold ( h a , f ) ende

En mere avanceret implementering giver dig mulighed for at kontrollere typerne af udtryk ved hjælp af Fold.

Eksempel: variabelt antal funktionsargumenter val sum = fn z => Fold . fold ( 0 , fn s => s ) z sjov a i = Fold . step0 ( fn s => i + s ) ... sum ( a 1 ) ( a 2 ) ( a 3 ) $ (* val it : int = 6 *)

Eksempel: liste bogstaver val liste = fn z => Fold . fold ([], rev ) z val ' = fn z => Fold . step1 ( op :: ) z ... liste 'w 'x 'y 'z $

Eksempel: (kosmetisk) afhængige typer val f = fn z => Fold . fold ((), id ) z val a = fn z => Fold . step0 ( fn () => "hej" ) z val b = fn z => Fold . step0 ( fn () => 13 ) z val c = fn z => Fold . step0 ( fn () => ( 1 , 2 )) z ... f a $ = "hej" : streng f b $ = 13 : int f c $ = ( 1 , 2 ): int * int

Programeksempler

Hej Verden!

Det enkleste SML-program kan skrives på én linje:

udskriv "Hej verden! \n "

Men i betragtning af sprogets fokus på programmering i stor skala , bør dets indpakning i modulsproget stadig betragtes som minimal (nogle compilere fungerer kun med programmer på modulniveau).

detaljer signatur HELLO_WORLD = sig val helloworld : unit -> unit end struktur HelloWorld : HELLO_WORLD = struktur sjov helloworld () = udskriv "Hello World! \n " slutning

Generelt kan enhver funktion vælges som udgangspunkt for programmet, men i praksis giver det mening at følge almindeligt accepterede konventioner, så du bør tilføje følgende kode:

struktur Main = struct fun main ( navn : streng , args : strengliste ) : OS . _ proces . status = lad val _ = HelloWorld . helloworld () i OS . proces . succes ende ende

For SML/NJ compileren skal du også tilføje en specifik linje til strukturen :Main

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

For programmer med flere moduler skal du også oprette en afhængighedssporingsprojektfil i compilermanageren (nogle compilere gør dette automatisk). For eksempel, for SML/NJ , skal du oprette en fil med sources.cmfølgende indhold:

gruppe signatur HELLO_WORLD struktur Hello World er helloworld-sig.sml helloworld.sml ende

En mere alsidig (men noget mere begrænset) mulighed med hensyn til understøttelse af forskellige compilere ville være at oprette en almindelig SML-kildekodefil med en lineær opregning af inkluderende filer:

brug "helloworld-sig.sml" ; brug "helloworld.sml" ;

Uddatamaskinkoden for et minimalt program er også relativt stor (sammenlignet med Hello World- implementeringer i C), fordi selv det mindste SML-program skal indeholde sprogets runtime-system , hvoraf det meste er skraldeopsamleren . Man bør dog ikke opfatte størrelsen af ​​kilde- og maskinkoderne i den indledende fase som tyngden af ​​SML: deres årsag er sprogets intensive fokus på udviklingen af ​​store og komplekse systemer. Yderligere vækst af programmer følger en meget fladere kurve end i de fleste andre statisk indtastede sprog, og overhead bliver knap mærkbar, når man udvikler seriøse programmer [71] .

Automatisk layout

fun firstLine s = lad val ( navn , hvile ) = Delstreng . splitl ( fn c => c <> #"." ) ( Understreng . fuld s ) i " \n <P><EM>" ^ Understreng . strengnavn ^ " </EM>" ^ Understreng . snor hvile ende sjov htmlCvt filnavn = lad val er = TextIO . openIn filnavn og os = TextIO . openOut ( filnavn ^ ".html" ) sjov cvt _ INGEN = () | cvt _ ( SOME " \n " ) = cvt true ( TextIO . inputLine er ) | cvt first ( SOME s ) = ( TextIO . output ( os , hvis først firstLine s else "<br>" ^ s ); cvt false ( TextIO . inputLine er ) ) i cvt true ( SOME " \n " ); tekstio . closeIn er ; tekstio . closeOut os ende

Denne kode konverterer flad tekst til HTML på den enkleste måde og formaterer dialogen efter roller [72] .

Demonstration af arbejde

Lad os sige, at vi har følgende tekstfil med navnet Henry.txt:

Westmoreland. Af kæmpende mænd har de fulde tre tusinde. Exeter. Der er fem til én; desuden er de alle friske. Westmoreland. 0, som vi nu havde her Men ti tusinde af de mænd i England Det virker ikke i dag! Kong Henrik V. Hvad er det ham, der ønsker det? Min fætter Westmoreland? Nej, min skønne fætter: Hvis vi er mærket til at dø, er vi nok At gøre vores land tab; og om at leve Jo færre mænd, jo større andel af ære.

Kald derefter programmet med følgende linje:

val_ = htmlCvt " Henry.txt "

Vil oprette en fil med Henry.txt.htmlfølgende indhold:

<P><EM>Westmoreland</EM>. Af kæmpende mænd har de fulde tre tusinde. <P><EM>Exeter</EM>. Der er fem til én; desuden er de alle friske. <P><EM>Westmoreland</EM>. 0, som vi nu havde her <br>Men en ti tusind af disse mænd i England <br>Det virker ikke i dag! <P><EM>Kong Henrik V</EM>. Hvad er det ham, der ønsker det? Hvad er min fætter Westmoreland? Nej, min skønne fætter: <br>Hvis vi er mærket til at dø, er vi nok <br>At gøre vores land tab; og om at leve <br>Jo færre mænd, jo større andel af ære.

Denne fil kan åbnes i en browser ved at se følgende:

Westmoreland. Af kæmpende mænd har de fulde tre tusinde.

Exeter. Der er fem til én; desuden er de alle friske.

Westmoreland. 0, som vi nu havde her
Men ti tusinde af de mænd i England
, som ikke gør noget arbejde i dag!

Kong Henrik V. Hvad er det ham, der ønsker det?
Min fætter Westmoreland? Nej, min smukke fætter:
Hvis vi er mærket til at dø, er vi nok
til at gøre vores land tab; og hvis man skal leve,
jo færre mænd, jo større andel af ære.

Ternære træer

Til opgaven med at slå en streng op i en ordbog, kombinerer ternære træer lynhastigheden af ​​præfikstræer med hukommelseseffektiviteten af ​​binære træer .

type key = Key . ord_key type item = Nøgle . ord_key list datatype sæt = LEAF | NODE af { key : key , lt : set , eq : set , gt : set } val tom = LEAF undtagelse Allerede til stede sjovt medlem (_, LEAF ) = falsk | medlem ( h::t , NODE { key , lt , eq , gt }) = ( case Key . compare ( h , key ) af EQUAL => medlem ( t , eq ) | MINDRE => medlem ( h::t , lt ) | STØRRE => medlem ( h::t , gt ) ) | medlem ([], NODE { key , lt , eq , gt }) = ( case Key . compare ( Key . sentinel , key ) af EQUAL => sand | MINDRE => medlem ([], lt ) | STØRRE => medlem ([], gt ) ) sjovt insert ( h::t , LEAF ) = NODE { key = h , eq = insert ( t , LEAF ), lt = LEAF , gt = LEAF } | indsæt ([], LEAF ) = NODE { key = Key . sentinel , eq = LEAF , lt = LEAF , gt = LEAF } | indsæt ( h::t , NODE { key , lt , eq , gt }) = ( case Key . compare ( h , key ) af EQUAL => NODE { key = key , lt = lt , gt = gt , eq = indsæt ( t , eq )} | MINDRE => NODE { key = key , lt = indsæt ( h::t , lt ), gt = gt , eq = eq } | STØRRE => NODE { key = key , lt = lt , gt = indsæt ( h::t , gt ), eq = eq } ) | indsæt ([], NODE { key , lt , eq , gt }) = ( case Key . compare ( Key . sentinel , key ) af EQUAL => hæv AlleredePresent | LESS => NODE { key = key , lt = indsæt ([ ], lt ), gt = gt , eq = eq } | STØRRE => NODE { key = key , lt = lt , gt = indsæt ([], gt ), eq = eq } ) sjov tilføje ( l , n ) = indsæt ( l , n ) håndtag AlleredeNuværende => n

Denne kode bruger en basisstruktur , Keyder kan sammenlignes med signatur ORD_KEY, såvel som en global type order(over hvilken især funktionen er defineret Key.compare):

datatype rækkefølge = MINDRE | LIG | STØRRE

Om sproget

Ydeevne

De typiske fordele ved funktionel programmering ( typesikkerhed , automatisk hukommelsesstyring , et højt abstraktionsniveau osv.) kommer til udtryk ved at sikre programmernes pålidelighed og overordnede ydeevne, og i kritiske, især store opgaver, hastighed ofte spiller en sekundær rolle. Vægten på disse egenskaber har historisk set ført til, at mange effektive datastrukturer (arrays, strenge, bitstrenge) ofte ikke er tilgængelige for programmører i funktionelle sprog, så funktionelle programmer er normalt mærkbart mindre effektive end tilsvarende C -programmer . [73]

ML giver i starten ret god finkornet hastighedskontrol , men historisk har ML-implementeringer været ekstremt langsomme. Men tilbage i begyndelsen af ​​1990'erne læste Andrew Appel [74] , at SML-sproget er hurtigere end C -sproget , i det mindste når man arbejder intensivt med komplekse strukturerede data (men SML hævder ikke at være en erstatning for C i problemer med systemprogrammering ). I løbet af de næste par år førte hårdt arbejde med udviklingen af ​​compilere til, at hastigheden for udførelse af SML-programmer steg med 20-40 gange [75] .

I slutningen af ​​1990'erne satte Steven Wicks sig for at opnå den højest mulige ydeevne fra SML-programmer og skrev en defunctorizer til SML/NJ , som straks viste en stigning i hastigheden med yderligere 2-3 gange. Yderligere arbejde i denne retning førte til skabelsen af ​​MLton compileren , som i midten af ​​2000'erne af det 21. århundrede viste en stigning i hastighed i forhold til andre compilere med et gennemsnit på to størrelsesordener [45] , konkurrerende med C (for flere detaljer, se MLton ).

Strategien med automatisk hukommelsesstyring baseret på regionsinferens eliminerer omkostningerne ved initialisering og frigivelse af hukommelse fra programudførelse (det vil sige, den implementerer skraldindsamling på kompileringsstadiet). ML Kit- kompileren bruger denne strategi til at løse problemer i realtid , selvom den er ringere end MLton med hensyn til optimeringsmuligheder.

Baseret på SML/NJ frontend , blev en compiler til kildekode i C udviklet  - sml2c . Det producerer kode af god kvalitet, men det er bemærkelsesværdigt, at " først til C, derefter til native " kompileringsskemaet sænker ydeevnen med op til to gange sammenlignet med direkte kompilering af SML til native kode på grund af semantiske forskelle mellem SML og C [5] .

Nogle SML-kompilere giver mulighed for at profilere koden for at bestemme de funktioner, der tager mest processortid (og resultatet er altid uventet) [73] , hvorefter du kan fokusere på at optimere dem ved hjælp af SML, eller flytte dem til C kode via FFI .

Begrundelse for semantik

Generel information

Sprogets teoretiske grundlag er den polymorf-typede lambdaregning (System F) , begrænset af Let-polymorfisme .

"Definitionen"

Den officielle "standard" for sproget er The Definition , udgivet som en bog .  Definitionen er formuleret i strenge matematiske termer og har dokumenteret pålidelighed . Konsistens af definitionen giver en person mulighed for at kontrollere programmets korrekthed og beregne dets resultat uden at køre en specifik compiler; men på den anden side kræver definitionen en høj grad af færdighed at forstå og kan ikke tjene som lærebog i sproget [74] .

Bevisbarheden af ​​pålidelighed kom ikke af sig selv - Definitionen blev revideret flere gange, før den så dagens lys. Mange sprog er afhængige af generelle teorier, men under udvikling bliver de næsten aldrig testet for sikkerheden ved at dele specifikke sprogelementer, der er særlige anvendelser af disse teorier, hvilket uundgåeligt fører til inkompatibilitet mellem sprogimplementeringer. Disse problemer ignoreres enten eller præsenteres som et naturligt fænomen ( eng.  "not a bug, but a feature" ), men i virkeligheden er de forårsaget af, at sproget ikke har været udsat for matematisk analyse [76] .

detaljer

Den originale definition, " The Definition of Standard ML ", blev offentliggjort i 1990 [2] . Et år senere blev "Comments on the Definition" (" Kommentarer til Standard ML ") offentliggjort, som forklarer de anvendte tilgange og notationer [77] . Sammen danner de specifikationen for det sprog, der nu er kendt som " SML'90 ". I løbet af de følgende år dukkede en række kritikpunkter og forslag til forbedring op (en af ​​de mest kendte er Harper-Lilybridges gennemsigtige summer ), og i 1997 blev mange af disse samlet i en revideret version af definitionen, " Definitionen af Standard ML: Revideret " [3] , der definerer en version af SML'97- sproget , der er bagudkompatibel med det tidligere. Den reviderede definition bruger principperne beskrevet i 1991-kommentarerne, så de, der har til hensigt at studere SML-definitionen grundigt, rådes til at studere SML'90 først, og først derefter SML'97. [78]

Med tiden blev der fundet en række uklarheder og udeladelser i teksten til definitionen [79] [80] [81] . Men de forringer ikke definitionens strenghed i det væsentlige - beviset for dens pålidelighed blev mekaniseret i Twelf [82] . De fleste implementeringer overholder definitionen ganske strengt, afvigende i tekniske funktioner - binære formater, FFI osv., såvel som i fortolkningen af ​​tvetydige steder i definitionen - alt dette fører til behovet for en vis ekstra indsats (meget mindre end for de fleste andre sprog) for at sikre perfekt portabilitet af rigtige SML-programmer mellem implementeringer (små programmer har i de fleste tilfælde ingen porteringsproblemer).

SML-definitionen er et eksempel på strukturel operationel semantik ; det er ikke den første formelle definition af sproget, men den første, der er utvetydigt forstået af kompilatorudviklere [83] .

Definitionen opererer på semantiske objekter , der beskriver deres betydning ( betydning ). I indledningen understreger forfatterne, at det er semantiske objekter (som afhængigt af det specifikke sprog kan omfatte begreber som en pakke, modul, struktur, undtagelse, kanal, type, procedure, link, medbrug osv.) og ikke syntaks , definere en konceptuel repræsentation af et programmeringssprog, og det er på dem, definitionen af ​​ethvert sprog skal bygges [84] .

Indhold

Ifølge definitionen er SML opdelt i tre sprog, bygget oven på hinanden: et bundlag kaldet " Kernesproget " ( kernesproget ), et mellemlag kaldet " moduler " ( moduler ) og et lille øverste lag kaldet " Programmer " ( Programmer ), som er en samling af topniveaudefinitioner ( topniveaudeklarationer ).

Definitionen omfatter omkring 200 slutningsregler ( inferens ), skrevet i form af en almindelig brøk, hvor den formaliserede sætning ML er i tællerpositionen, og konsekvensen, som kan konkluderes, hvis sætningen er korrekt, er i nævnerpositionen .

Definitionen skelner mellem tre hovedfaser i sproget [85] [86] : parsing ( parsing ), udvikling ( elaboration ) og evaluering ( evaluation ). Working out refererer til statisk semantik; beregning - til dynamisk. Men evalueringen her skal ikke forveksles med execution ( execution ): SML er et udtryksbaseret sprog ( expression-based language ), og at få et resultat ved at anvende en funktion på alle argumenter kaldes execution ( execution ), og "evaluering af en funktion" betyder at bygge en definition af det selv. Det skal også bemærkes, at understøttelsen af ​​currying på sproget betyder, at alle funktioner er repræsenteret ved lukninger , og det betyder igen, at det er forkert at bruge udtrykket "funktionskald". I stedet for at kalde , bør vi tale om funktionsapplikation ( funktionsapplikation ) - funktionen kan simpelthen ikke kaldes, før den modtager alle argumenterne; delvis anvendelse af en funktion betyder evaluering af en ny funktion (en ny lukning ). For hvert af sprogets lag (kerne, moduler, programmer) beskrives statisk og dynamisk semantik separat, det vil sige stadierne af analyse, udvikling og beregning.

En særlig implementering af sproget er ikke påkrævet for at foretage alle disse skel, de er kun formelle [86] . Faktisk er den eneste implementering, der stræber efter at håndhæve dem strengt, HaMLet . Især betyder produktion uden evaluering det traditionelle begreb kompilering.

Evalueringen af ​​hver definition i løbet af programmet ændrer tilstanden af ​​det globale miljø ( miljø på øverste niveau ), kaldet grundlaget . Formelt er programmets udførelse beregningen af ​​et nyt grundlag som summen af ​​det indledende grundlag og programdefinitioner. Standardbiblioteket i SML er "standardgrundlaget", som er tilgængeligt for alle programmer fra begyndelsen, og kaldes derfor blot Basis. Selve definitionen indeholder kun det indledende grundlag ( initial basis ), der indeholder de minimum nødvendige definitioner; det mere omfattende Basis blev standardiseret meget senere, efter at have gennemgået en længere udvikling i praksis .

Harper-Stone semantik

Harper-Stone semantik ( HS semantik for kort ) er en fortolkning af SML i en maskinskrevet ramme .  XC-semantikken for SML er defineret gennem udviklingen af ​​den eksterne SML til et internt sprog, som er en eksplicit maskinskrevet lambdaregning , og dermed fungerer som den typeteoretiske begrundelse for sproget. Denne fortolkning kan ses som et alternativ til Definitionen , der formaliserer "statiske semantiske objekter" i form af maskinskrevne lambda-calculus udtryk; og også som en deklarativ beskrivelse af genereringsreglerne for typestyrede compilere som TILT eller SML/NJ . Faktisk inkarnerer frontenden af ​​TILT-kompileren denne semantik, selvom den blev udviklet flere år tidligere. [87] [88] [89]  

Det interne sprog er baseret på Harper-Mitchells XML-sprog, men har et større sæt af primitiver og et mere udtryksfuldt modulsystem baseret på Harper-Lilybridges gennemsigtige summer . Dette sprog er velegnet til udvikling af mange andre sprog, hvis semantik er baseret på lambda-regningen , såsom Haskell og Scheme .

Denne tilgang er indbygget i det efterfølgende ML - projekt . Samtidig betragtes ændringer i sproget, som ikke påvirker det indre sprog, som et kortsigtet perspektiv ( eng.  kortsigtet ), og som kræver ændringer - som et langsigtet perspektiv ( eng.  langsigtet ).

Kritik og sammenligning med alternativer

Udviklerne af SML satte sproget til den højeste kvalitetsstandard fra starten, så tærsklen for kritik er meget højere end de fleste industrisprog. Omtaler om SML-sprogets mangler findes i den officielle presse lige så ofte som i C++-sproget og meget oftere end de fleste andre sprog, men årsagen er slet ikke en negativ holdning til SML - tværtimod, enhver kritik af SML fremsættes med en meget varm holdning til det. Selv en pedantisk analyse af manglerne ved SML ledsages normalt af dens beskrivelse som "et fantastisk sprog, det eneste seriøse sprog, der eksisterer " [90] . Med andre ord, forskerne dykker grundigt ned i manglerne og antyder, at selv når man tager dem i betragtning, viser SML sig at være mere at foretrække til brug i gigantiske videnskabstunge projekter end mange mere populære sprog, og ønsker at bringe SML til perfektion.

Fordele

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

Fejl

Hovedproblemet for SML-udvikleren i dag er det dårlige udviklingsniveau af miljøet (især IDE ) og biblioteksudvikling.

SML-sikkerhed betyder overhead på aritmetik: På grund af kravet om, at hver operation skal have identisk adfærd på hver platform, er overløbstjek , division med nul osv. væsentlige komponenter i enhver aritmetisk operation. Dette gør sproget til et ineffektivt valg til problemer med nummerknuser , især for pipelinede arkitekturer [91] .

Sammenligning med OKaml :

[92] [93] [94]

OKaml er den nærmeste slægtning til SML, efter at have skilt sig fra det selv før standardisering. OKaml er så bredt udviklet, at det nogle gange i spøg omtales som " SML++ ". Inden for masseprogrammering er OCaml betydeligt foran SML i popularitet; i akademiske kredse er SML meget oftere genstand for videnskabelig forskning. OCaml hovedudvikler Xavier Leroy er medlem af efterfølgeren ML bestyrelsen .

OCaml har en enkelt implementering, der inkluderer to compilere (til bytekode og til native), som er næsten identisk kompatible, og som konstant udvikler sig og tilbyder ikke kun bedre miljøer, men også mere og mere kraftfulde semantiske funktioner. SML har mange forskellige implementeringer, der følger den samme sprogdefinition og kernebibliotek, og nogle gange tilbyder yderligere funktioner.

De vigtigste forskelle er i semantikken for typeækvivalens. For det første i SML er funktorer generatorer, mens de i OCaml er applikative (se typeækvivalens i ML-modulsproget ). For det andet understøtter OCaml ikke lighedstypevariabler : lighedsoperationen accepterer objekter af enhver type, men kaster en undtagelse, hvis de er inkompatible .

Moderne versioner af OCaml inkluderer semantiske funktioner, der kun er tilgængelige individuelt i nogle SML-udvidelser, såsom:

Sammenligning med Haskell :

Haskell er arving til ML/SML (i denne forstand er der normalt ingen grundlæggende forskel mellem ML og SML). Begge sprog er baseret på Hindley -Milner-typesystemet , inklusive typeinferens , hvorfra der er mange ligheder [95] ( førsteklasses funktioner , typesikker parametrisk polymorfi , algebraiske datatyper og mønstermatchning på dem) .

Blandt de vigtigste forskelle er [95] [96] [97] [98] [99] [68] [100] :

Historie, filosofi, terminologi

Den formelle semantik af SML er fortolkningsorienteret , men de fleste af dens implementeringer er compilere (inklusive interaktive compilere), hvoraf nogle med sikkerhed konkurrerer i effektivitet med C -sproget , da sproget egner sig godt til global analyse. Af samme grund kan SML kompileres til kildekode på andre sprog på højt eller mellemniveau - for eksempel er der kompilatorer fra SML til C og Ada .

Sproget er baseret på stærk statisk polymorf typning, som ikke kun sikrer programverifikation på kompileringsstadiet, men også strengt adskiller mutabilitet , hvilket i sig selv øger potentialet for automatisk programoptimering - især forenkler implementeringen af ​​skraldeopsamleren [104 ] .

Den første version af ML blev introduceret til verden i 1974 som et metasprog til at bygge interaktive beviser som en del af Edinburgh LCF (Logic for Computable Functions) systemet [2] . Det blev implementeret af Malcolm Newey, Lockwood Morris og Robin Milner på DEC10-platformen. Den første implementering var ekstremt ineffektiv, da ML-konstruktioner blev oversat til Lisp , som derefter blev fortolket [105] . Den første fuldstændige beskrivelse af ML som en del af LCF blev offentliggjort i 1979 [2] .

Omkring 1980 implementerede Luca Cardelli den første Vax ML compiler , og tilføjede nogle af hans ideer til ML. Cardelli overførte snart Vax ML til Unix ved hjælp af Berkley Pascal. Kørselstiden blev omskrevet i C , men det meste af compileren forblev i Pascal. Cardellis arbejde inspirerede Milner til at skabe SML som et almindeligt sprog i sig selv, og de begyndte at arbejde sammen i Edinburgh , hvilket resulterede i Edinburgh ML compileren , udgivet i 1984. I løbet af dette arbejde kom Mike Gordon med referencetyper og foreslog dem til Louis Damas, som senere lavede sin afhandling om dem [106] . Samtidig samarbejdede Cambridge med INRIA. Gerard Hugh fra INRIA overførte ML til Maclisp under Multics. INRIA udviklede deres egen dialekt af ML kaldet Caml, som senere udviklede sig til OCaml . Lawrence Paulson har optimeret Edinburgh ML , så ML-koden kører 4-5 gange hurtigere. Kort efter udviklede David Matthews Poly-sproget baseret på ML. Yderligere arbejde i denne retning førte til skabelsen af ​​Poly/ML miljøet . I 1986 formulerede David McQueen ML-modulets sprog , og Andrew Appel sluttede sig til arbejdet Sammen påbegyndte de arbejdet med SML/NJ compileren , der både fungerede som en forskningsplatform for sprogudvikling og branchens første optimerende compiler. Mange af sprogimplementeringerne blev oprindeligt udviklet ved hjælp af SML/NJ og derefter promoveret .

Med erfaringerne fra storstilet udvikling blev en række mangler i sprogdefinitionen fra 1990 opdaget . Nogle af manglerne blev rettet i 1997-revisionen af ​​definitionen [3] , men omfanget af revisionen eliminerer tabet af bagudkompatibilitet (koder tilpasser sig kosmetisk uden behov for at omskrive fra bunden). I 2004 udkom specifikationen for sammensætningen af ​​Grundbiblioteket (et udkast til specifikationen går tilbage til 1996 ). Andre mangler er blevet rettet på andre sprog: ML skabte en hel familie af X-M-type sprog . Disse sprog har vundet popularitet på opgaven med sprogdesign og defineres ofte som " DSL'er for denotationel semantik . Forskere, der har været involveret i udviklingen og brugen af ​​SML i næsten tre årtier, dannede i slutningen af ​​det 20. århundrede et fællesskab for at skabe en ny sproglig efterfølger ML .

Faktisk var SML ikke den første i familien efter selve LCF/ML - det blev forudgået af sprog som Cardelli ML og Hope [9] . Franskmændene opretholder deres egen dialekt - Caml / OCaml [12] . Men når man siger "ML", mener mange mennesker "SML" [107] , og skriver endda gennem brøken: "ML/SML" [82] .

Udforsker

Den mest anbefalede [108] [109] [110] [111] [112] [113] lærebog om SML er ML for Working Programmer [107] af Lawrence Paulson (forfatter af HOL -systemet ) .

For en indledende introduktion til sproget, et kort (adskillige dusin sider) kursus " Introduction to Standard ML " af Robert Harper (tilgængelig i russisk oversættelse [114] ), som han brugte til at undervise i sproget og udvidede i løbet af de næste to årtier til mere større lærebog [115] .

Ricardo Pucellas bog [30] tjener som en tutorial til brug af sprogets standardbibliotek, forudsat en grundlæggende viden om det .

Andre lærebøger omfatter bøger af Gilmore [116] , Ullman [117] , Shipman [118] , Cummings online bog [119] .

Blandt guiderne til den professionelle brug af sproget kan man fremhæve bogen af ​​Andrew Appel (hovedudvikler af SML/NJ ) " Modern compiler implementering i ML " [120] (denne bog har to tvillingesøstre : " Moderne compilerimplementering i Java " og " Moderne compilerimplementering i C ", som er ækvivalente i strukturen, men bruger andre sprog til at implementere de skitserede metoder). Der er også mange artikler publiceret i tidsskrifter såsom JFP , ML workshop osv. [121] [122]

Ansøgning

SML fungerer sammen med OCaml som det første undervisningssprog til undervisning i programmering på mange universiteter rundt om i verden. Blandt anvendelige sprog har de sandsynligvis den laveste adgangstærskel af deres egne.

En væsentlig del af den eksisterende SML-kode er enten en implementering af dens egne compilere eller automatiske bevissystemer som HOL , Twelf og Isabelle (automatiseret teorem-bevissystem). Alle er gratis og åbne .

Der er dog også mere "mundanne", herunder proprietære produkter [123] .

Noter

  1. SML'84, 1984 .
  2. 1 2 3 4 SML'90, 1990 .
  3. 1 2 3 SML'97, 1997 .
  4. SML'90, 1990 , E. Tillæg: Udviklingen af ​​ML, s. 81-83.
  5. 1 2 3 Tarditi et al, "No Assembly Required", 1990 .
  6. 1 2 Tolmach, Oliva, "Fra ML til Ada", 1993 .
  7. 1 2 Kommentar til SML, 1991 , s. v.
  8. 1 2 Pucella, "Notes on SML/NJ", 2001 , s. en.
  9. 1 2 3 4 MacQueen, "Reflections on SML", 1992 .
  10. StandardML beskrivelse i MLton compiler guide . Hentet 14. august 2016. Arkiveret fra originalen 25. august 2016.
  11. 1 2 ML2000 Preliminary Design, 1999 .
  12. 1 2 Paulson, "ML for the Working Programmer", 1996 , s. 12.
  13. Paulson, "ML for the Working Programmer", 1996 , s. 2.
  14. Rossberg, "1ML", 2015 .
  15. Harper-Stone '99, 1999 .
  16. 1 2 Paulson, "ML for the Working Programmer", 1996 , 4.13 Træbaserede datastrukturer, s. 148-149.
  17. 12 OOP i SML .
  18. MacQueen, "Reflections on SML", 1992 , s. 2.
  19. Kommentar til SML, 1991 , s. femten.
  20. Paulson, "ML for the Working Programmer", 1996 , Imperative Programming in ML, s. 313.
  21. MacQueen, "Reflections on SML", 1992 , s. 3.
  22. Paulson, "ML for the Working Programmer", 1996 , s. en.
  23. 1 2 Appel, "A Critique of Standard ML", 1992 , Mangel på makroer, s. 9.
  24. 1 2 VandenBerghe, "Hvorfor ML/OCaml er gode til at skrive compilere", 1998 .
  25. Paulson, "ML for the Working Programmer", 1996 , 7.8 Testing af køstrukturerne, s. 274.
  26. MacQueen, "Reflections on SML", 1992 , s. 6.
  27. 1 2 Paulson, "ML for the Working Programmer", 1996 , 2.3 Identifiers in Standard ML, s. 21.
  28. Paulson, "ML for the Working Programmer", 1996 , s. 13.
  29. SML Basis, 2004 .
  30. 1 2 Pucella, "Notes on SML/NJ", 2001 .
  31. Pucella, "Notes on SML/NJ", 2001 , 4.3. Mere om strenge, s. 89-92.
  32. Pucella, "Notes on SML/NJ", 2001 , 4.3. Mere om strenge, s. 90.
  33. 1 2 Standard ML-portabilitet .
  34. SML/NJ-projektets hjemmeside . Hentet 14. august 2016. Arkiveret fra originalen 1. maj 2020.
  35. Afvigelser af SML/NJ fra definitionen af ​​SML'97 (revideret) . Hentet 14. august 2016. Arkiveret fra originalen 4. april 2016.
  36. SML/NJ: Indlejring af objektsprog med citat/anticitat . Hentet 14. august 2016. Arkiveret fra originalen 19. juni 2016.
  37. Slind, "Sprogindlejring i SML/NJ", 1991 .
  38. Poly/ML-projektets hjemmeside Arkiveret 27. juni 2020 på Wayback Machine
  39. ML Kit-projektwebsted (utilgængeligt link) . Hentet 14. august 2016. Arkiveret fra originalen 19. juli 2016. 
  40. 1 2 Project Manticore hjemmeside . Hentet 14. august 2016. Arkiveret fra originalen 8. august 2016.
  41. CakeML projektwebsted . Hentet 14. august 2016. Arkiveret fra originalen 14. september 2020.
  42. sml-evolution konference: Rober Harper, 30/10/2006.
  43. Shao, "FLINT/ML Compiler", 1997 .
  44. webstedet for MoscowML-projektet . Hentet 14. august 2016. Arkiveret fra originalen 11. januar 2016.
  45. 12 MLton ydeevne .
  46. SML.NET projektwebsted . Hentet 14. august 2016. Arkiveret fra originalen 29. januar 2016.
  47. SMLtoJs projektwebsted (downlink) . Hentet 14. august 2016. Arkiveret fra originalen 14. september 2016. 
  48. SMLonline-side (downlink) . Hentet 14. august 2016. Arkiveret fra originalen 2. oktober 2016. 
  49. sml2c kildekoder . Hentet 14. august 2016. Arkiveret fra originalen 28. august 2018.
  50. Fra ML til Ada - beskrivelse i MLton compiler guide (downlink) . Hentet 16. september 2016. Arkiveret fra originalen 23. september 2016. 
  51. Koser, Larsen, Vaughan, "SML2Java", 2003 .
  52. HaMLet projektside . Hentet 14. august 2016. Arkiveret fra originalen 14. oktober 2016.
  53. Isabelle/ML-projektets hjemmeside . Hentet 26. august 2016. Arkiveret fra originalen 30. august 2020.
  54. Poplog-projektwebsted . Hentet 26. august 2016. Arkiveret fra originalen 18. august 2016.
  55. Standard ML-projektGitHub
  56. SML# projektwebsted . Hentet 14. august 2016. Arkiveret fra originalen 8. juni 2020.
  57. Mythril-projektwebsted . Hentet 14. august 2016. Arkiveret fra originalen 28. juni 2009.
  58. Taha et al, "Macros as Multi-Stage Computations", 2001 .
  59. Pucella, "Notes on SML/NJ", 2001 , kapitel 6. The Compilation Manager, s. 157.
  60. eXene - multi-threaded X Window System-værktøjssæt skrevet i ConcurrentML . Hentet 14. august 2016. Arkiveret fra originalen 22. februar 2012.
  61. Huelsbergen, "Portable C Interface for SML", 1996 .
  62. Chris Cannam, "Hvorfor var OCaml hurtigere?" .
  63. Blume, "No-longer-foreign", 2001 .
  64. Standard ML Style Guide (fra MLton guide) . Hentet 14. august 2016. Arkiveret fra originalen 27. august 2016.
  65. Appel, "A Critique of Standard ML", 1992 , Fejlstavede konstruktører, s. 12.
  66. Harper, "Intro to SML", 1986 , s. 5.
  67. "EtaExpansion"-teknik (fra MLton Guide) . Hentet 6. september 2016. Arkiveret fra originalen 10. september 2016.
  68. 1 2 Peyton-Jones, "retrospective on Haskell", 2003 .
  69. Typeindekserede værdier (fra MLton Guide) . Hentet 26. august 2016. Arkiveret fra originalen 21. april 2016.
  70. "Fold"-teknik (fra MLton Guide) . Hentet 24. august 2016. Arkiveret fra originalen 26. september 2016.
  71. Shipman, "Unix-programmering med SML", 2001 , s. 31.
  72. Paulson, "ML for the Working Programmer", 1996 , 8.9 Eksempler på tekstbehandling, s. 348-350.
  73. 1 2 Paulson, "ML for the Working Programmer", 1996 , 1.5 The efficiency of functional programmering, s. 9.
  74. 1 2 3 Appel, "A Critique of Standard ML", 1992 .
  75. Paulson, "ML for the Working Programmer", 1996 , s. 108.
  76. Commentary on SML, 1991 , Aims of the Commentary, s. vii.
  77. Kommentar til SML, 1991 .
  78. om definitionen af ​​standard ML i MLton guide  (downlink)
  79. Kahrs, 1993 .
  80. Kahrs, 1996 .
  81. Defekter i SML (fra HaMLet manual) . Hentet 6. september 2016. Arkiveret fra originalen 4. maj 2016.
  82. 12 sml-family.org . _
  83. Paulson, "ML for the Working Programmer", 1996 , 1.9 ML and the working programmeur, s. 16.
  84. SML'90, 1990 , s. v.
  85. SML'90, 1990 , s. en.
  86. 1 2 Kommentar til SML, 1991 , s. 1-3.
  87. Harper-Stone '96, 1996 .
  88. Harper-Stone '97, 1997 .
  89. Harper-Stone '99, 1999 , s. 1-2.
  90. 1 2 Rossberg, "Defects in SML Revised", 2001 .
  91. Harper, "Programming in SML", 2005 , 12.1.1 Primitive Exceptions, s. 104.
  92. Chris Cannam, "Fire ML'er (og 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, "Lightweight high-kinded polymorphism", 2014 .
  98. 1 2 Augustsson, "Mislykket eventyr i Haskell Abstraction" .
  99. Wehr, Chakravarty, "Modules vs. Type Classes", 2008 .
  100. Harper, "Selvfølgelig har ML monader!" .
  101. Paulson, "ML for the Working Programmer", 1996 , Sequences, or infinite lists, s. 191-201.
  102. Kommentar til SML, 1991 , 3 Dynamic Semantics for the Modules, s. 26.
  103. Rossberg, "1ML", 2015 , s. 2.
  104. Appel, "A Critique of Standard ML", 1992 , Efficiency, s. 7-8.
  105. Paulson, "ML for the Working Programmer", 1996 , s. elleve.
  106. MacQueen, "Cardelli and Early Evolution of ML", 2014 , s. fire.
  107. 1 2 Paulson, "ML for the Working Programmer", 1996 .
  108. Anbefalede bøger på SML/NJ compiler side . Hentet 26. august 2016. Arkiveret fra originalen 19. august 2016.
  109. Gilmore, "Programming in SML. Tutorial Introduction", 1997 , s. 3.
  110. Shipman, "Unix-programmering med SML", 2001 , s. 455.
  111. MacQueen, "Reflections on SML", 1992 , s. en.
  112. Pucella, "Notes on SML/NJ", 2001 , s. 42.
  113. SML-grundlag på Cambridge University Press-relaterede bøger . Hentet 19. maj 2022. Arkiveret fra originalen 24. februar 2021.
  114. Harper, "Intro til SML", 1986 .
  115. Harper, "Programming in SML", 2005 .
  116. Gilmore, "Programming in SML. Tutorial Introduction", 1997 .
  117. Ullman, "Elements of ML Programming", 1998 .
  118. Shipman, "Unix-programmering med SML", 2001 .
  119. Cumming, 1995 .
  120. Appel, "Moderne compilerimplementering i ML", 1998 .
  121. Fluet, Pucella, "Phantom Types and Subtyping", 2006 .
  122. Pucella, "Reactive Programming in SML", 2004 .
  123. Standard ML-brugere . Hentet 14. august 2016. Arkiveret fra originalen 10. september 2016.

Litteratur

Standarder

Tutorials, guider, opslagsbøger, brug

  • Robert Harper Introduktion til Standard ML. - Carnegie Mellon University, 1986. - 97 s. — ISBN PA 15213-3891.
  • Konrad Slind. Objektsprogsindlejring i Standard ML i New Jersey. - Proceedings of the 2nd ML workshop, Carnegie Mellon University., 1991.
  • Lawrence C. Paulson . ML for den arbejdende programmør. — 2. - Cambridge, Storbritannien: Cambridge University Press, 1996. - 492 s. -ISBN 0-521-57050-6(hardcover), 0-521-56543-X (softcover).
  • Jeffrey Ullman. Elementer i ML-  programmering . - Prentice-Hall, 1998. - ISBN 0-13-790387-1 .
  • Andrew W. Appel. Moderne compilerimplementering i ML  . - Cambridge, Storbritannien: Cambridge University Press, 1998. - 538 s. - ISBN 0-521-58274-1 (hardback), 0-521-60764-7 (paperback).
  • Anthony L. Shipman. Unix-systemprogrammering med standard  ML . – 2001.
  • Riccardo Pucella. Bemærkninger om programmeringsstandard ML i New  Jersey . - Sidst revideret 10. januar 2001. - Cornell University, 2001.
  • Bernard Berthomieu. OO programmeringsstile 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.

Historie, analyse, kritik

  • Milner , Morris, Newey. En logik for beregnelige funktioner med refleksive og polymorfe typer // Arc-et-Senans. — Proc. Konference om at bevise og forbedre programmer, 1975.
  • Gordon, Milner , Morris, Newey, Wadsworth. Et metasprog til interaktivt bevis i LCF. - 1977.
  • David McQueen. Strukturer og parametrisering i et maskinskrevet funktionssprog. - 1981.
  • Andrew Appel, David MacQueen. Separat kompilering for Standard ML  . - SIGPLAN 94-6/94, ACM 0-89791-662-x/94/006, 1994. - doi : 10.1.1.14.4810 .
  • Stefan Kahrs. Fejl og uklarheder i definitionen af ​​standard ML-  tillæg . - University of Edinburgh, 1996.  (utilgængeligt link)
  • Robert Harper , Christopher A. Stone. En typeteoretisk redegørelse for Standard ML // Technical Report CMU-CS-96-136R. - Carnegie Mellon University, 1996.
  • Robert Harper , Christopher A. Stone. En fortolkning af Standard ML i typeteori // Teknisk rapport CMU-CS-97-147. - Carnegie Mellon University, 1997.
  • Andreas Rossberg, Claudio Russo, Derek Dreyer. F-ing  moduler . — TLDI, 2010.

Diverse

  • Derek Dreyer, Robert Harper . Modulære typeklasser  . — ACM SIGPLAN, 2007.

Links