- Flix ist eine von der Aarhus University und der Open-Source-Community entwickelte effektorientierte Sprache, die funktionale, imperative und logische Programmierung in einer Sprache vereint
- Im Zentrum steht ein Effektsystem, das Nebenwirkungen auf Typebene behandelt und durch Reinheitsverfolgung, benutzerdefinierte Effekte, Handler und mehrfache Wiederaufnahmen Modularität und bessere Schlussfolgerbarkeit ermöglicht
- Die Sprachoberfläche ist breit aufgestellt und umfasst algebraische Datentypen, Pattern Matching, erweiterbare Records, Traits, Higher-Kinded Types, assoziierte Typen und Effekte, strukturierte Nebenläufigkeit, Java-Interoperabilität und eingebautes Datalog
- Die Standardbibliothek bietet mehr als 3.100 Funktionen und ermöglicht über Maven auch den Zugriff auf das Java-Ökosystem, wodurch der Einsatz über reine Forschungssprachen hinausgehen soll
- Der Compiler zielt auf JVM-Bytecode ab und ist parallel sowie inkrementell aufgebaut; auf einer 24-Core-Maschine werden 5x–7x Geschwindigkeitssteigerung sowie ein Durchsatz von 60.159 lines/sec unter Apple M2 Pro/OpenJDK 21 angegeben
Die Ausrichtung von Flix
- Flix ist eine prinzipienbasierte effektorientierte Sprache, die funktionale, imperative und logische Programmierung kombiniert
- Entwickelt wird sie von der Aarhus University und der Community der Open-Source-Mitwirkenden
- Das Effektsystem ist eine zentrale Säule der statisch typisierten Sprache und unterstützt durch explizite Modellierung von Nebenwirkungen Modularität und Programmanalyse
- Über benutzerdefinierte Effekte und Handler können Programmierer Kontrollstrukturen selbst implementieren
- Flix hebt sich unter den effektorientierten Sprachen durch eine ausgereifte Implementierung, eine breite Standardbibliothek, ausführliche Dokumentation und Tool-Unterstützung hervor
Typen, Reinheit und Effektsystem
- Flix unterstützt algebraische Datentypen und Pattern Matching als grundlegende Elemente funktionaler Programmierung
- Tupel und Records werden nativ unterstützt; Records verwenden strukturelle Typisierung und sind erweiterbar
- Der Compiler verfolgt die Reinheit aller Ausdrücke im Programm präzise
- Ist ein Ausdruck rein, ist garantiert, dass er keine Nebenwirkungen hat und referenztransparent ist
- Auch bei Higher-Order Functions wird Reinheit durch Effektpolymorphie verfolgt
- So hängt etwa die Reinheit von
List.mapvon der Reinheit der als Argument übergebenen Funktionfab
- So hängt etwa die Reinheit von
- Algebraische Effekte ermöglichen benutzerdefinierte Effekte und Handler
- Flix unterstützt dabei insbesondere multi-shot resumptions
- Effekt-Handler werden genutzt, um Programmanalyse, Modularität und Testbarkeit zu verbessern
Regionsbasierte Mutation und Reinheitsreflexion
- Flix unterstützt regionsbasierte lokale Mutation, sodass intern veränderbarer Zustand und destruktive Operationen verwendet werden können, nach außen aber weiterhin eine reine Funktion sichtbar ist
- Das eignet sich für Funktionen, die sich natürlicher mit veränderbaren Daten schreiben lassen, oder für Fälle wie Sortieralgorithmen, bei denen veränderbare Datenstrukturen effizienter sind
- Reinheitsreflexion ist eine Metaprogrammierungsstruktur, bei der Higher-Order Functions die Reinheit von Funktionsargumenten prüfen und ihr Verhalten davon abhängig machen
DelayList.mapwechselt je nach Reinheit der Argumentfunktion zwischen sofortiger und verzögerter Auswertung- Selbst wenn innerhalb der Bibliothek wahlweise Lazy Evaluation oder parallele Auswertung genutzt wird, muss sich die Bedeutung aus Sicht des Clients nicht ändern
Parallelität, Nebenläufigkeit und Abstraktion
- Flix macht es leicht, reinen Code parallel auszuwerten, und mit der
par-Struktur lässt sich eine parallele Implementierung vonList.mapschreiben - Die
par-Struktur verwendet intern leichtgewichtige VirtualThread - Es wird strukturierte Nebenläufigkeit unterstützt, sodass Threads, die in einer bestimmten Region erzeugt werden, nicht über den Lebenszyklus dieser Region hinaus bestehen können
- Im Beispiel werden zwei Threads in einer neuen Region namens
rcerzeugt - Der Kontrollfluss verlässt die Region erst, wenn beide Threads beendet sind
- Im Beispiel werden zwei Threads in einer neuen Region namens
- Für Typabstraktionen, die gemeinsame Operationen unterstützen, werden Traits verwendet
- Das
Eq-Trait beschreibt das Konzept von Gleichheit und wird in der gesamten Standardbibliothek verwendet
- Das
- Mit Higher-Kinded Types lassen sich Typkonstruktoren abstrahieren
OptionundListimplementieren beideFoldable- Die Standardbibliothek enthält gemeinsame Traits wie
Monoid,FunctorundFoldable
Assoziierte Typen, assoziierte Effekte und for-yield
- Flix unterstützt assoziierte Typen, sodass der Typ einer Instanzsignatur vom Instanztyp abhängen kann
- Im Beispiel des
Coll-Traits kann jede Collection-Instanz über den assoziierten TypElmihren Elementtyp definieren
- Im Beispiel des
- Assoziierte Effekte sorgen dafür, dass der Effekt eines Trait-Members vom Instanztyp abhängt
- Dadurch lassen sich reine und effektbehaftete Operationen sowie veränderbare und unveränderliche Datenstrukturen leichter gemeinsam abstrahieren
- Fügt man dem
Coll-Trait den assoziierten EffektAefhinzu, können auch veränderbare Collection-Instanzen ergänzt werden
forM-yield ist eine monadische Struktur ähnlich wiefor-comprehensions in Scala oder diedo-Notation in Haskell- Es handelt sich um syntaktischen Zucker für die Nutzung von
pointundflatMap, die dasMonad-Trait bereitstellt
- Es handelt sich um syntaktischen Zucker für die Nutzung von
forAist ein applicativer Ausdruck auf Basis desApplicative-Traits- Die Struktur hilft dabei, Fehlerbehandlungscode mit dem Datentyp
Validation[e, t]einfach zu schreiben
- Die Struktur hilft dabei, Fehlerbehandlungscode mit dem Datentyp
Java-Interoperabilität und Datalog
- Flix unterstützt Java-Interoperabilität, sodass sich die Java Standard Library und Code aus dem Java-Ökosystem wiederverwenden lassen
- Einschließlich des Zugriffs auf das Ökosystem über Maven
- Unterstützt werden Objekterzeugung, Methodenaufrufe, Ausnahmen sowie das Erweitern von Klassen und Interfaces
- Die eingebaute Unterstützung für Datalog ist eine der besonderen Funktionen von Flix
- Mit Datalog lassen sich viele Fixpunktprobleme, darunter auch Erreichbarkeitsprobleme in Graphen, prägnant ausdrücken
- Datalog-Constraints sind Werte erster Klasse
- Sie können an Funktionen übergeben oder von Funktionen zurückgegeben werden
- Sie können in Datenstrukturen gespeichert werden
- Sie können mit anderen Datalog-Constraints kombiniert und gelöst werden
- Dadurch lassen sich ganze Familien von Datalog-Programmen ausdrücken
- Flix unterstützt auch Datalog-Constraints mit erweiteter Gittersemantik
- Es gibt ein Beispiel zur Berechnung von Lieferterminen für Bauteile und Unterbaugruppen
- Ein Auto hängt von Fahrgestell und Motor ab und kann erst montiert werden, nachdem die Montage aller Komponenten abgeschlossen ist
- Auch Unterbaugruppen können wiederum von weiteren Unterbaugruppen abhängen, sodass das Problem rekursiv ist
- Datalog-Constraints mit Gittersemantik gehören zu den fortgeschrittenen Funktionen von Flix und setzen Kenntnisse in Gittertheorie und Fixpunkten voraus
Standardbibliothek und Funktionsliste
- Flix enthält eine Standardbibliothek mit mehr als 3.100 Funktionen
- Das Modul
Listbietet mehr als 100 Funktionen - Das Trait
Foldablebietet mehr als 47 Funktionen - Die gesamte Bibliothek kann unter api.flix.dev erkundet werden
- Das Modul
- Zur Funktionsliste gehören unter anderem
- algebraische Datentypen, Pattern Matching, Funktionen erster Klasse
- erweiterbare Records, parametrische Polymorphie
- Traits, Higher-Kinded Types, assoziierte Typen und Effekte
- Effektpolymorphie und Sub-Effekte, Reinheitsreflexion
- Nebenläufigkeit im CSP-Stil, gepufferte und ungepufferte Channels
- Datalog-Constraints erster Klasse, Java-Interoperabilität
- unboxed primitive Typen, schlüsselwortbasierte Syntax
forM,forA, Expression Holes- Kompilierung zu JVM-Bytecode, vollständige Tail-Call-Eliminierung
- elastische und parallele Compiler-Architektur, menschenlesbare Fehlermeldungen
Compiler-Architektur und Leistung
- Der Flix-Compiler ist elastisch, inkrementell und parallel aufgebaut
- Alle Compiler-Phasen laufen parallel, sodass auf einer 24-Core-Maschine die Beschleunigung jeder Phase genutzt werden kann
- Auf Multicore-Maschinen sind 5x–7x Geschwindigkeitssteigerung möglich
- Wenn bereits kompilierter Code innerhalb derselben Compiler-Instanz erneut kompiliert wird, kann inkrementelle Kompilierung deutliche Beschleunigungen bringen
- Auf Basis einer Apple M2 Pro CPU mit 10 Kernen und OpenJDK 21 werden folgende Leistungswerte angegeben
- Gesamtdurchsatz des Compilers: 60.159 lines/sec
- Durchsatz nur des Frontends: 140.382 lines/sec
- Die Reproduktionsbefehle sind
java -jar flix.jar Xperf --n 21undjava -jar flix.jar Xperf --frontend --n 21
- Diese Leistung wird erreicht, obwohl kostenintensive Sprachmerkmale wie Typ- und Effektinferenz, Monomorphisierung und Whole-Program-Optimierung unterstützt werden
- Die Compiler-Leistung wird hauptsächlich durch CPU-Leistung und Speicherbandbreite bestimmt
Unterstützung für Visual Studio Code und Tool-Integration
- Der Flix-Compiler ist in Visual Studio Code integriert und stellt damit eine Entwicklungsumgebung bereit
- Die VSCode-Erweiterung verwendet den echten Flix-Compiler, daher besteht eine 1:1-Entsprechung zwischen Erweiterung und Compiler
- Wenn VSCode keinen Fehler meldet, gibt es keinen Fehler
- Wenn kein Fehler vorliegt, meldet VSCode auch keine falschen Fehler
- Die VSCode-Erweiterung unterstützt folgende Funktionen
- semantisches Syntax-Highlighting
- Inline-Diagnosen von Compilerfehlern
- Autovervollständigung beim Tippen, kontextabhängige Vervollständigung, Vervollständigung von Trait-Instanzen, typbasierte Hole-Vervollständigung
- Snippets und Inlay-Hints
- Hover-Anzeigen für Typ und Effekt von Ausdrücken
- Navigation zu Funktionen, lokalen Variablen und Enum-Definitionen
- Finden von Referenzen auf Funktionen, lokale Variablen und Enums sowie Finden von Trait-Implementierungen
- Listen von Dokument- und Workspace-Symbolen
- Umbenennen lokaler Variablen und Funktionsnamen
- Ausführen von main und Tests direkt im Editor
- Flix integriert viele Werkzeuge direkt in den Compiler
- OCaml nutzt
ocaml-lspals LSP,utopals REPL,duneals Build-Tool undopamals Paketmanager - Haskell nutzt
HLSals LSP,ghcials REPL,cabalundstackals Build-Tool und Paketmanager sowieHackageals Paket-Repository - Flix stellt Compiler, LSP, REPL, Build-Tool und Paketmanager allesamt über
flixbereit, das Paket-Repository ist GitHub
- OCaml nutzt
Entwicklungsstand, JVM-Ziel und Projektgröße
- Flix wird von Forschern im Bereich Programmiersprachen an der dänischen Aarhus University entwickelt und gepflegt
- Kooperationspartner sind die kanadische University of Waterloo, die deutsche University of Tubingen und die dänische Copenhagen University
- Die Beteiligung der weltweiten Open-Source-Community am Projekt wächst, Beiträge sind willkommen
- Die Projektstatistiken lauten wie folgt
- gemergte Pull Requests: mehr als 4.900
- gelöste Issues: mehr als 3.100
- Mitwirkende: mehr als 70
- Codebasis des Compilers: mehr als 272.000 Zeilen
- Flix zielt auf die JVM ab
- Für die JVM gibt es bewährte Open-Source- und kommerzielle Implementierungen wie OpenJDK, J9, Azul und Graal
- Flix ist unter Mac, Linux und Windows nutzbar
- Moderne JVMs bieten mehrere aktuelle Garbage Collectors
- Auch die Unterstützung für Nebenläufigkeit und Parallelität ist stark, einschließlich leichtgewichtiger Threads in Java 21
- Es gibt Tool-Unterstützung einschließlich Debuggern und Profilern
- Über die Maven-Integration ist Zugang zum umfangreichen Paket-Ökosystem der Java-Plattform möglich
- Die Gesamtfinanzierung beträgt 1,1 Millionen Euro und hilft dabei, Kontinuität und Unabhängigkeit des Projekts zu sichern
Noch keine Kommentare.