Standard ML

Standard ml
Paradigma Multi-Paradigma: funktional, Imperativ, modular[1]
Familie Ml
Erstmals erschienen 1983; Vor 39 Jahren[2]
Stabile Version
Standard ML '97[2] / 1997; vor 25 Jahren
Disziplin tippen Gefolgert, statisch, stark
Dateiname -Erweiterungen .Sml
Webseite Smlfamily.Github.io
Haupt Implementierungen
Sml/nj, Mlton
Dialekte
Alice, Gleichzeitiger ML, Abhängig ml
Beeinflusst von
Ml, Hoffnung, Pascal
Beeinflusst
Ulme, F#, F*, Haskell, Ocaml, Python,[3] Rost, Scala

Standard ml (Sml) ist eine allgemeine modulare funktionelle Programmiersprache mit Überprüfung des Kompilierzeittyps und Typ-Inferenz. Es ist unter dem beliebten unter Compiler Schriftsteller und Programmiersprache Forschersowie bei der Entwicklung von Theoremprover.

Standard ML ist ein moderner Dialekt von Ml, die in der verwendete Sprache Logik für berechnbare Funktionen (LCF) Theorem-Proving-Projekt. Es unterscheidet sich unter weit verbreiteten Sprachen darin, dass es eine formale Spezifikation hat, die als angegeben ist Schreibregeln und Betriebssemantik in Die Definition von Standard ML.[4]

Sprache

Standard ML ist eine funktionale Programmiersprache mit einigen unreinen Merkmalen. Programme, die in Standard -ML geschrieben wurden, bestehen aus Ausdrücke im Gegensatz zu Aussagen oder Befehlen, obwohl einige Ausdrücke vom Typ Einheit werden nur für ihre bewertet Nebenwirkungen.

Funktionen

Wie alle funktionalen Sprachen ist eine Schlüsselfunktion von Standard ML die Funktion, die zur Abstraktion verwendet wird. Die faktorielle Funktion kann wie folgt ausgedrückt werden:

Spaß Fakultät n =   wenn n = 0 dann 1 anders n * Fakultät (n - 1) 

Geben Sie Inferenz ein

Ein SML -Compiler muss den statischen Typ schließen val factorial : int -> int ohne benutzerversorgte Typanmerkungen. Das muss das ableiten n wird nur mit ganzzahligen Ausdrücken verwendet und muss daher selbst eine Ganzzahl sein, und alle terminalen Ausdrücke sind ganzzahlige Ausdrücke.

Deklarative Definitionen

Die gleiche Funktion kann mit klausalen Funktionsdefinitionen ausgedrückt werden, wobei die wenn-dann-anders Die Bedingung wird durch Vorlagen der faktoriellen Funktion ersetzt, die für bestimmte Werte bewertet wurde:

Spaß Fakultät 0 = 1  | Fakultät n = n * Fakultät (n - 1) 

Imperative Definitionen

oder iterativ:

Spaß Fakultät n = Lassen val i = Ref n und Acc = Ref 1 in  während !ich > 0 tun (Acc : = ! Acc * !ich; i : = !ich - 1); ! Acc Ende 

Lambda Funktionen

oder als Lambda -Funktion:

val Rec Fakultät = fn 0 => 1 | n => n * Fakultät (n - 1) 

Hier das Schlüsselwort val führt eine Bindung einer Kennung an einen Wert ein, fn führt ein vor Anonyme Funktion, und rec Ermöglicht die Definition selbstreferenziell.

Lokale Definitionen

Die Einkapselung einer invarianten Präparation des schwanzrekursiven engen Schleife mit einem oder mehreren Akkumulatorparametern in einer invarianten freien äußeren Funktion ist, wie hier zu sehen ist, eine gemeinsame Idiom in Standard-ML.

Mit einer lokalen Funktion kann sie in einem effizienteren Schwanzrezisivstil umgeschrieben werden:

lokal  Spaß Schleife (0, Acc) = Acc  | Schleife (m, Acc) = Schleife (m - 1, m * Acc) in  Spaß Fakultät n = Schleife (n, 1) Ende 

Geben Sie Synonyme ein

Ein Typ -Synonym ist mit dem Schlüsselwort definiert type. Hier ist ein Typ Synonym für Punkte auf a Flugzeugund Funktionen, die die Entfernungen zwischen zwei Punkten und der Fläche eines Dreiecks mit den gegebenen Ecken wie PER berechnen Herons Formel. (Diese Definitionen werden in nachfolgenden Beispielen verwendet).

Typ loc = real * real Spaß Quadrat (x : real) = x * x Spaß distieren (x, y) (x', y ') =  Mathematik.sqrt (Quadrat (x' - x) + Quadrat (y ' - y)) Spaß Reiher (a, b, c) = Lassen  val x = distieren a b  val y = distieren b c  val z = distieren a c  val s = (x + y + z) / 2.0  in  Mathematik.sqrt (s * (s - x) * (s - y) * (s - z))  Ende 

Algebraische Datentypen

Standard ML bietet eine starke Unterstützung für Algebraische Datentypen (ADT). Ein Datentyp kann als als betrachtet werden Union Union von Tupeln (oder einer "Summe von Produkten"). Sie sind leicht zu definieren und einfach zu bedienen, vor allem wegen von Musteranpassung sowie die meisten Standard -ML -Implementierungen ' Musterexhautivität Überprüfung der Überprüfung und Musterreduktion.

In objektorientierten Programmiersprachen kann eine disjunkte Gewerkschaft ausgedrückt werden als Klassenhierarchien. Im Gegensatz zu Klassenhierarchien sind ADTs jedoch abgeschlossen. Somit ist die Erweiterbarkeit von ADTs orthogonal gegenüber der Erweiterbarkeit von Klassenhierarchien. Klassenhierarchien können mit neuen Unterklassen erweitert werden, die dieselbe Schnittstelle implementieren, während die Funktionalität von ADTs für den festen Satz von Konstruktoren erweitert werden kann. Sehen Ausdrucksproblem.

Ein Datentyp wird mit dem Schlüsselwort definiert datatype, wie in:

Datentyp Form  = Kreis  von loc * real  ( * Mitte und Radius *)  | Quadrat  von loc * real  ( * obere linke Ecke und Seitenlänge; Achse ausgerichtet *)  | Dreieck von loc * loc * loc ( * Ecken *) 

Beachten Sie, dass ein Typ -Synonym nicht rekursiv sein kann. Datenatypen sind erforderlich, um rekursive Konstruktoren zu definieren. (Dies ist in diesem Beispiel nicht in Frage.)

Musteranpassung

Muster sind in der Reihenfolge übereinstimmen, in der sie definiert sind. C -Programmierer können verwenden Markierte Gewerkschaften, Versand auf Tag -Werten, um das zu erreichen, was ML mit DataTypen und Musteranpassungen erreicht. Während ein C -Programm, das mit geeigneten Schecks dekoriert ist, in gewissem Sinne so robust ist wie das entsprechende ML -Programm, werden diese Überprüfungen jedoch notwendigerweise dynamisch sein. MLs Statische Überprüfungen Geben Sie starke Garantien für die Richtigkeit des Programms zur Kompilierungszeit.

Funktionsargumente können als Muster wie folgt definiert werden:

Spaß Bereich (Kreis (_, r)) = Mathematik.Pi * Quadrat r  | Bereich (Quadrat (_, s)) = Quadrat s  | Bereich (Dreieck p) = Reiher p (* siehe oben *) 

Die sogenannte "klausale Form" der Funktionsdefinition, bei der Argumente als Muster definiert werden, ist lediglich syntethischer Zucker Für einen Fallausdruck:

Spaß Bereich Form = Fall Form von  Kreis (_, r) => Mathematik.Pi * Quadrat r  | Quadrat (_, s) => Quadrat s  | Dreieck p => Reiher p 

Schalldämmungsprüfung

Durch die Überprüfung der Musterexhautigkeit stellt sicher, dass jeder Konstruktor des Datentyps mit mindestens einem Muster übereinstimmt.

Das folgende Muster ist nicht erschöpfend:

Spaß Center (Kreis (c, _)) = c  | Center (Quadrat ((x, y), s)) = (x + s / 2.0, y + s / 2.0) 

Es gibt kein Muster für die Triangle Fall in der center Funktion. Der Compiler wird eine Warnung geben, dass der Fallausdruck nicht erschöpfend ist und ob a Triangle wird zur Laufzeit an diese Funktion übergeben, exception Match wird erhoben.

Redundanzprüfung

Das Muster in der zweiten Klausel der folgenden (bedeutungslosen) Funktion ist überflüssig:

Spaß f (Kreis ((x, y), r)) = x + y  | f (Kreis _) = 1.0  | f _ = 0,0 

Jeder Wert, der mit dem Muster in der zweiten Klausel übereinstimmt, würde auch mit dem Muster in der ersten Klausel übereinstimmen, sodass die zweite Klausel nicht erreichbar ist. Daher zeigt diese Definition als Ganzes Redundanz und führt zu einer Warnung für Kompilierzeit.

Die folgende Funktionsdefinition ist erschöpfend und nicht überflüssig:

val Hascorner = fn (Kreis _) => FALSCH | _ => Stimmt 

Wenn die Kontrolle über das erste Muster hinauskommt (Circle), wir wissen, dass die Form entweder a sein muss Square oder ein Triangle. In einem dieser Fälle wissen wir, dass die Form Ecken hat, sodass wir zurückkehren können true ohne die tatsächliche Form zu erkennen.

Funktionen höherer Ordnung

Funktionen können Funktionen als Argumente konsumieren:

Spaß Karte f (x, y) = (f x, f y) 

Funktionen können Funktionen als Rückgabewerte erzeugen:

Spaß Konstante k = (fn _ => k) 

Funktionen können auch Funktionen konsumieren und produzieren:

Spaß komponieren (f, g) = (fn x => f (g x)) 

Die Funktion List.map Aus der Basisbibliothek ist eine der am häufigsten verwendeten Funktionen höherer Ordnung in Standard-ML:

Spaß Karte _ [] = []  | Karte f (x :: xs) = f x :: Karte f xs 

Eine effizientere Implementierung mit Schwanzrekursiv List.foldl:

Spaß Karte f = Aufführen.rev o Aufführen.falten (fn (x, Acc) => f x :: Acc) [] 

Ausnahmen

Ausnahmen werden mit dem Keyword erhoben raise und mit dem Muster -Matching behandelt handle konstruieren. Das Ausnahmesystem kann den nicht lokalen Ausgang implementieren. Diese Optimierungstechnik ist für Funktionen wie die folgenden geeignet.

lokal  Ausnahme Null;  val p = fn (0, _) => heben Null | (a, b) => a * b in  Spaß prod xs = Aufführen.falten p 1 xs handhaben Null => 0 Ende 

Wann exception Zero wird angehoben, die Kontrolle verlässt die Funktion List.foldl insgesamt. Betrachten Sie die Alternative: Der Wert 0 würde zurückgegeben, sie würde mit der nächsten Ganzzahl in der Liste multipliziert, der resultierende Wert (unweigerlich 0) würde zurückgegeben und so weiter. Durch die Erhöhung der Ausnahme kann die Kontrolle die gesamte Kette von Frames überspringen und die zugehörige Berechnung vermeiden. Beachten Sie die Verwendung des Unterstrichs (_) als Wildcard -Muster.

Die gleiche Optimierung kann mit a erhalten werden Schwanzanruf.

lokal  Spaß p a (0 :: _) = 0  | p a (x :: xs) = p (a * x) xs  | p a [] = a in  val prod = p 1 Ende 

Modulsystem

Das fortschrittliche Modulsystem von Standard -ML ermöglicht es, Programmen in hierarchisch organisierte zu zersetzen Strukturen von logisch verwandten Typ- und Wertdefinitionen. Module liefern nicht nur Namespace Kontrolle, aber auch Abstraktion in dem Sinne, dass sie die Definition von erlauben Abstrakte Datentypen. Drei wichtigste syntaktische Konstrukte umfassen das Modulsystem: Signaturen, Strukturen und Funktoren.

Unterschriften

A Unterschrift ist ein Schnittstelle, normalerweise als Typ für eine Struktur angesehen; Es gibt die Namen aller von der Struktur bereitgestellten Entitäten sowie die an Arity jeder Typkomponente, der Typ jeder Wertkomponente und die Signatur jeder Unterstruktur. Die Definitionen der Typkomponenten sind optional; Typkomponenten, deren Definitionen versteckt sind abstrakte Typen.

Zum Beispiel die Signatur für a Warteschlange vielleicht:

Unterschrift WARTESCHLANGE = Sig  Typ 'a Warteschlange  Ausnahme QueueError;  val leer  : 'a Warteschlange  val ist leer  : 'a Warteschlange -> bool  val Singleton : 'a -> 'a Warteschlange  val von der Liste  : 'a aufführen -> 'a Warteschlange  val Einfügung  : 'a * 'a Warteschlange -> 'a Warteschlange  val spähen  : 'a Warteschlange -> 'a  val Löschen  : 'a Warteschlange -> 'a * 'a Warteschlange Ende 

Diese Signatur beschreibt ein Modul, das einen polymorphen Typ liefert 'a queue, exception QueueErrorund Werte, die grundlegende Operationen in Warteschlangen definieren.

Strukturen

A Struktur ist ein Modul; Es besteht aus einer Sammlung von Typen, Ausnahmen, Werten und Strukturen (genannt Unterstrukturen) zusammen in eine logische Einheit verpackt.

Eine Warteschlangenstruktur kann wie folgt implementiert werden:

Struktur Twolistqueue :> WARTESCHLANGE = Struktur  Typ 'a Warteschlange = 'a aufführen * 'a aufführen  Ausnahme QueueError;  val leer = ([], [])  Spaß ist leer ([], []) = Stimmt  | ist leer _ = FALSCH  Spaß Singleton a = ([], [a]))  Spaß von der Liste a = ([], a)  Spaß Einfügung (a, ([], [])) = Singleton a  | Einfügung (a, (Ins, Outs)) = (a :: Ins, Outs)  Spaß spähen (_, []) = heben QueueError  | spähen (Ins, Outs) = Aufführen.HD Outs  Spaß Löschen (_, []) = heben QueueError  | Löschen (Ins, [a])) = (a, ([], Aufführen.rev Ins))  | Löschen (Ins, a :: Outs) = (a, (Ins, Outs)) Ende 

Diese Definition erklärt das structure TwoListQueue Geräte signature QUEUE. Außerdem die undurchsichtige Zuschreibung bezeichnet durch :> stellt fest, dass alle Typen, die nicht in der Signatur definiert sind (d. H. type 'a queue) sollte abstrakt sein, was bedeutet, dass die Definition einer Warteschlange als Listenpaar außerhalb des Moduls nicht sichtbar ist. Die Struktur implementiert alle Definitionen in der Signatur.

Die Typen und Werte in einer Struktur können mit "Punktnotation" zugegriffen werden:

val q : Saite Twolistqueue.Warteschlange = Twolistqueue.leer val q' = Twolistqueue.Einfügung (Real.tostring Mathematik.Pi, q) 

Funkern

A Functor ist eine Funktion von Strukturen zu Strukturen; Das heißt, ein Functor akzeptiert ein oder mehrere Argumente, die normalerweise Strukturen einer bestimmten Signatur sind und als Ergebnis eine Struktur erzeugen. Funktionen werden zur Implementierung verwendet generisch Datenstrukturen und Algorithmen.

Ein beliebter Algorithmus[5] zum Breite-First-Suche von Bäumen benutzt Warteschlangen. Hier präsentieren wir eine Version dieses Algorithmus, das über eine abstrakte Warteschlangenstruktur parametrisiert ist:

( * Nach Okasaki, ICFP, 2000 *) Functor BFS (Q: WARTESCHLANGE) = Struktur  Datentyp 'a Baum = E | T von 'a * 'a Baum * 'a Baum  lokal  Spaß BFSQ q = wenn Q.ist leer q dann [] anders Suche (Q.Löschen q)  und Suche (E, q) = BFSQ q  | Suche (T (x, l, r), q) = x :: BFSQ (Einfügung (Einfügung q l) r)  und Einfügung q a = Q.Einfügung (a, q)  in  Spaß BFS t = BFSQ (Q.Singleton t)  Ende Ende Struktur Queuebfs = BFS (Twolistqueue) 

Innerhalb functor BFSDie Darstellung der Warteschlange ist nicht sichtbar. Konkreter ist es nicht möglich, die erste Liste in der Zwei-Listen-Warteschlange auszuwählen, wenn dies tatsächlich die verwendete Darstellung ist. Dies Datenabstraktion Mechanismus macht die Breite zuerst die Suche nach der Implementierung der Warteschlange wirklich agnostisch. Dies ist im Allgemeinen wünschenswert; In diesem Fall kann die Warteschlangenstruktur alle logischen Invarianten beibehalten, von denen ihre Richtigkeit von der kugelsicheren Abstraktionswand abhängt.

Codebeispiele

Snippets von SML -Code werden am einfachsten untersucht, indem sie in eine eingeben Interaktive obere Ebene.

Hallo Welt

Das Folgende ist a Hallo Welt! Programm:

hello.sml
drucken "Hallo Welt!\n" 
verprügeln
$ Mlton Hello.sml$ ./halloHallo Welt! 

Algorithmen

Sortieren durch Einfügen

Einfügung Sortierung für int list (aufsteigend) kann genau wie folgt ausgedrückt werden:

Spaß Einfügung (x, []) = [x] | Einfügung (x, h :: t) = Sortieren x (h, t) und Sortieren x (h, t) = wenn x < h dann [x, h] @ t anders h :: Einfügung (x, t) val Sortieren durch Einfügen = Aufführen.falten Einfügung [] 

Zusammenführen, sortieren

Hier wird der klassische Mergesort -Algorithmus in drei Funktionen implementiert: Split, Merge und Mergesort. Beachten Sie auch das Fehlen von Typen mit Ausnahme der Syntax op :: und [] die Listen bedeuten. Dieser Code sortiert Listen jeglicher Art, solange eine konsistente Bestellfunktion cmp ist definiert. Verwendung Hindley -Milner -Typ -InferenzDie Arten aller Variablen können abgeleitet werden, sogar komplizierte Typen wie die der Funktion cmp.

Teilt

fun split wird mit a implementiert Staatsbürgerlich Schließung, der sich wechselt zwischen true und false, ignorieren die Eingabe:

Spaß Generator {} = Lassen val Zustand = Ref Stimmt  in fn a => !Zustand Vor Zustand : = nicht (!Zustand) Ende (* Teilen Sie eine Liste in nahezu Halbes auf, die entweder die gleiche Länge haben,  * Oder das erste hat ein mehr Element als das andere.  * Läuft in o (n) Zeit, wo n = | xs |.  *) Spaß Teilt xs = Aufführen.Trennwand (Generator {}) xs 

Verschmelzen

Merge verwendet eine lokale Funktionsschleife zur Effizienz. Das Innere loop wird in Bezug auf Fälle definiert: Wenn beide Listen nicht leer sind (nicht leer sind (x :: xs) und wenn eine Liste leer ist ([]).

Diese Funktion verschmilzt zwei sortierte Listen in eine sortierte Liste. Beachten Sie, wie der Akkumulator acc ist rückwärts gebaut und dann umgekehrt, bevor er zurückgekehrt ist. Dies ist eine gemeinsame Technik, da seitdem 'a list ist als a verlinkte Liste; Diese Technik erfordert mehr Uhrzeit, aber die Asymptotik sind nicht schlechter.

(* Fusionieren Sie zwei bestellte Listen mit der Bestellung CMP.  * PRE: Jede Liste muss bereits pro CMP bestellt werden.  * Läuft in o (n) Zeit, wo n = | xs | + | ys |.  *) Spaß verschmelzen CMP (xs, []) = xs  | verschmelzen CMP (xs, y :: ys) = Lassen  Spaß Schleife (a, Acc) (xs, []) = Aufführen.revappend (a :: Acc, xs)  | Schleife (a, Acc) (xs, y :: ys) =  wenn CMP (a, y)  dann Schleife (y, a :: Acc) (ys, xs)  anders Schleife (a, y :: Acc) (xs, ys)  in  Schleife (y, []) (ys, xs)  Ende 

Zusammenführen, sortieren

Die Hauptfunktion:

Spaß AP f (x, y) = (f x, f y) (* Sortieren Sie eine Liste gemäß dem angegebenen Bestellvorgang CMP.  * Läuft in O (n log n) Zeit, wo n = | xs |.  *) Spaß Zusammenführen, sortieren CMP [] = []  | Zusammenführen, sortieren CMP [x] = [x]  | Zusammenführen, sortieren CMP xs = (verschmelzen CMP o AP (Zusammenführen, sortieren CMP) o Teilt) xs 

Schnelle Sorte

Quicksort kann wie folgt ausgedrückt werden. fun part ist ein Schließung Das verbraucht einen Bestellbetreiber op <<.

Infix << Spaß schnelle Sorte (op <<) = Lassen  Spaß Teil p = Aufführen.Trennwand (fn x => x << p)  Spaß Sortieren [] = []  | Sortieren (p :: xs) = beitreten p (Teil p xs)  und beitreten p (l, r) = Sortieren l @ p :: Sortieren r  in  Sortieren  Ende 

Ausdrucksinterpreter

Beachten Sie die relative Leichtigkeit, mit der eine kleine Ausdruckssprache definiert und verarbeitet werden kann:

Ausnahme Tyerr; Datentyp ty = Intty | Boolty Spaß vereinheitlichen (Intty, Intty) = Intty  | vereinheitlichen (Boolty, Boolty) = Boolty  | vereinheitlichen (_, _) = heben Tyerr Datentyp Exp  = WAHR  | FALSCH  | Int von int  | Nicht von Exp  | Hinzufügen von Exp * Exp  | Wenn  von Exp * Exp * Exp Spaß schließen WAHR = Boolty  | schließen FALSCH = Boolty  | schließen (Int _) = Intty  | schließen (Nicht e) = (behaupten e Boolty; Boolty)  | schließen (Hinzufügen (a, b)) = (behaupten a Intty; behaupten b Intty; Intty)  | schließen (Wenn (e, t, f)) = (behaupten e Boolty; vereinheitlichen (schließen t, schließen f)) und behaupten e t = vereinheitlichen (schließen e, t) Spaß bewerten WAHR = WAHR  | bewerten FALSCH = FALSCH  | bewerten (Int n) = Int n  | bewerten (Nicht e) = wenn bewerten e = WAHR dann FALSCH anders WAHR  | bewerten (Hinzufügen (a, b)) = (Fall (bewerten a, bewerten b) von (Int x, Int y) => Int (x + y))  | bewerten (Wenn (e, t, f)) = bewerten (wenn bewerten e = WAHR dann t anders f) Spaß Lauf e = (schließen e; ETWAS (bewerten e)) handhaben Tyerr => KEINER 

Beispiel Verwendung bei gut typischen und schlecht getotischen Ausdrücken:

val ETWAS (Int 3) = Lauf (Hinzufügen (Int 1, Int 2)) ( * gut typisch *) val KEINER = Lauf (Wenn (Nicht (Int 1), WAHR, FALSCH)) ( * Ill-typed *) 

Willkürliche Prezisionszahlen

Das IntInf Das Modul bietet eine beliebige Ganzzahlarithmetik. Darüber hinaus können ganzzahlige Literale als zahlreiche Zahlen für willkürliche Präzision verwendet werden, ohne dass der Programmierer etwas tun muss.

Das folgende Programm implementiert eine beliebige faktorielle Funktion:

Fakt.Sml
Spaß Tatsache n : Intinf.int = wenn n = 0 dann 1 anders n * Tatsache (n - 1);  Spaß Drucklinie str = Lassen in   Textio.Ausgang (Textio.Stdout, str);   Textio.Ausgang (Textio.Stdout, "\n") Ende;  val () = Drucklinie (Intinf.tostring (Tatsache 120)); 
verprügeln
$ mlton fact.sml$ ./Tatsache6689502913449127057588118054090372586752746333138029810295671352301 6335572449629893668741652719849813081576378932140905525344085894081 21859898481114389650005964960521256960000000000000000000000000000 

Teilweise Anwendung

Curry -Funktionen haben viele Anwendungen, wie z. B. die Beseitigung redundanter Code. Beispielsweise kann ein Modul Funktionen vom Typ benötigen a -> b, aber es ist bequemer, Funktionen vom Typ zu schreiben a * c -> b wo es eine feste Beziehung zwischen den Objekten vom Typ gibt a und c. Eine Funktion des Typs c -> (a * c -> b) -> a -> b kann diese Gemeinsamkeit berücksichtigen. Dies ist ein Beispiel für das Adaptermuster.

In diesem Beispiel, fun d berechnet die numerische Ableitung einer bestimmten Funktion f am Punkt x:

- Spaß d Delta f x = (f (x + Delta) - f (x - Delta)) / (2.0 * Delta) val d = fn : real -> (real -> real) -> real -> real 

Die Art von fun d zeigt an, dass es einen "Schwimmer" auf eine Funktion mit dem Typ ordnet (real -> real) -> real -> real. Dies ermöglicht es uns, teilweise Argumente anzuwenden, die als als bekannt sind Currying. In diesem Fall Funktion d Kann spezialisiert werden, indem es teilweise mit dem Argument angewendet wird delta. Eine gute Wahl für delta Wenn Sie diesen Algorithmus verwenden, ist die Würfelwurzel des Maschine Epsilon.

- val d' = d 1e ~ 8; val d' = fn : (real -> real) -> real -> real 

Beachten Sie, dass der abgeleitete Typ das angibt d' erwartet eine Funktion mit dem Typ real -> real Als erstes Argument. Wir können eine Annäherung an das Derivat von berechnen bei . Die richtige Antwort ist .

- d' (fn x => x * x * x - x - 1.0) 3.0; val es = 25.99999996644 : real 

Bibliotheken

Standard

Basisbibliothek[6] wurde standardisiert und Schiffe mit den meisten Implementierungen. Es bietet Module für Bäume, Arrays und andere Datenstrukturen sowie Eingabe/Ausgabe- und Systemschnittstellen.

Dritte Seite

Für numerisches Computing existiert ein Matrixmodul (ist derzeit kaputt). https://www.cs.cmu.edu/afs/cs/project/pscico/pscico/src/matrix/readme.html.

Für Grafiken ist Cairo-SML eine Open-Source-Schnittstelle zum Kairo Grafikbibliothek. Für maschinelles Lernen gibt es eine Bibliothek für grafische Modelle.

Implementierungen

Implementierungen von Standard -ML enthalten die folgenden:

Standard

  • Weiler: Ein Standard -ML -Dolmetscher, der eine genaue und zugängliche Referenzimplementierung des Standards sein soll
  • Mlton (Mlton.org): a Ganzprogramm optimieren Compiler, der strikt der Definition entspricht und im Vergleich zu anderen ML -Implementierungen einen sehr schnellen Code erzeugt, einschließlich Backends zum Llvm und C
  • Moskau ML: Eine leichte Implementierung, basierend auf dem CAML Light Laufzeit -Engine, die die vollständige Standard -ML -Sprache implementiert, einschließlich Module und viel der Basisbibliothek
  • Poly/ml: Eine vollständige Implementierung von Standard -ML, die schnelle Code erzeugt und Multicore -Hardware unterstützt (über POSIX -Threads); Das Laufzeitsystem führt eine parallele Müllsammlung und die Online -Teile unveränderlicher Unterstrukturen durch.
  • Standard -ML von New Jersey (smlnj.org): Ein vollständiger Compiler mit zugehörigen Bibliotheken, Tools, einer interaktiven Hülle und Dokumentation mit Unterstützung für Gleichzeitiger ML
  • Sml.net: ein Standard -ML -Compiler für die Gemeinsame Sprachlaufzeit mit Erweiterungen für die Verknüpfung mit anderen .NETZ Code
  • ML Kit Archiviert 2016-01-07 im Wayback -Maschine: Eine Implementierung, die sehr genau auf der Definition basiert, integriert einen Müllsammler (der deaktiviert werden kann) und Regionbasierte Speicherverwaltung mit automatischer Inferenz von Regionen, um Echtzeitanwendungen zu unterstützen

Derivat

  • Alice: Ein Dolmetscher für Standard -ML der Saarland University mit Unterstützung für parallele Programmierung mit Verwendung Futures, faule Bewertung, verteiltes Computer über Remote -Verfahrensanrufe und Einschränkungsprogrammierung
  • SML#: Eine Erweiterung von SML, die Aufzeichnungspolymorphismus und C -Sprachinteroperabilität bietet. Es ist ein herkömmlicher einheimischer Compiler und sein Name ist nicht Eine Anspielung auf das Laufen im .NET -Framework
  • SOSML: Eine Implementierung geschrieben in Typoskriptden größten Teil der SML -Sprache unterstützen und Teile der Basisbibliothek auswählen

Forschung

  • Cakeml ist eine Repl -Version von ML mit formell verifizierter Laufzeit und Übersetzung zum Assembler.
  • Isabelle (Isabelle/ml) integriert parallele Poly/ml in einen interaktiven Theorem -Prover in eine ausgefeilte IDE (basierend auf Jedit) für offizielle Standard -ML (SML'97), der Isabelle/ML -Dialekt und die Beweissprache. Beginnend mit Isabelle2016 gibt es auch einen Debugger auf Quellenebene für ML.
  • Papplog implementiert eine Version von Standard ML zusammen mit Common Lisp und PrologMischsprachenprogrammierung zuzulassen; Alle sind in implementiert in Pop-11, welches ist inkrementell kompiliert.
  • NEIGUNG ist ein vollständig zertifizierender Compiler für Standard -ML, der Typed verwendet Zwischensprachen zu optimieren codieren und die Korrektheit sicherstellen und kompilieren können Typisierte Versammlungssprache.

Alle diese Implementierungen sind Open Source und frei verfügbar. Die meisten werden in Standard -ML implementiert. Es gibt keine kommerziellen Implementierungen mehr; Harlekin, jetzt nicht mehr als eine kommerzielle IDE und einen kommerziellen Compiler namens MLWorks produziert, der an weitergegeben wurde Xanalys und wurde später Open-Sourcing, nachdem es am 26. April 2013 von Ravenbrook Limited erworben wurde.

Hauptprojekte mit SML

Das IT University of Copenhagen'S Ganze Unternehmensstruktur wird in rund 100.000 SML-Zeilen implementiert, darunter Mitarbeiteraufzeichnungen, Gehaltsabrechnungen, Kursverwaltung und Feedback, Studentenprojektmanagement und webbasierte Self-Service-Schnittstellen.[7]

Das Proof Assistenten HOL4, Isabelle, LEGO, und Zwölf sind in Standard ml geschrieben. Es wird auch von verwendet von Compiler -Autoren und Integrierte Schaltungsdesigner wie zum Beispiel ARM.[8]

Siehe auch

Verweise

  1. ^ a b "Programmierung in Standard -ML: Hierarchien und Parametrisierung". Abgerufen 2020-02-22.
  2. ^ a b c "SML '97". www.smlnj.org.
  3. ^ a b "Itertools - Funktionen, Iteratoren für effiziente Schleifen zu erstellen - Python 3.7.1RC1 -Dokumentation". docs.python.org.
  4. ^ a b Robin Milner; Mads Toftte; Robert Harper; David MacQueen (1997). Die Definition von Standard ML (überarbeitet). MIT Press. ISBN 0-262-63181-4.
  5. ^ a b Chris Okasaki (2000). "Breite erste Nummerierung: Lehren aus einer kleinen Übung im Algorithmus-Design". Internationale Konferenz über funktionale Programmierung 2000. ACM.
  6. ^ "Standard -ML -Basisbibliothek". smlfamily.github.io. Abgerufen 2022-01-10.
  7. ^ a b Mads Toftte (2009). "Standard -ML -Sprache". Gelehrter. 4 (2): 7515. Bibcode:2009sschpj ... 4.7515t. doi:10.4249/Scholarpedia.7515. Abgerufen 2020-01-08.
  8. ^ a b Jade Alglave;Anthony C. J. Fox;Samin Ishtiaq;Magnus O. myreen;Susmit Sarkar;Peter Sewell;Francesco Zappa Nardelli. Die Semantik von Strom- und Arm -Multiprozessor -Maschinencode (PDF).Feuchter 2009. S. 13–24.

Externe Links

Über Standard ml

Über Nachfolger ml

Praktisch

Akademisch