- Ein Entwickler vergleicht auf Basis seiner Erfahrungen mit 8 Jahren Haskell und 8 Monaten OCaml in der Produktion das tatsächliche Entwicklungsgefühl der beiden funktionalen Sprachen
- Haskell bietet eine knappere Syntax und starke Typfunktionen, lenkt aber durch die große Zahl an Möglichkeiten leicht die Aufmerksamkeit auf Design und Abstraktion
- OCaml wird trotz weniger Features als Sprache bewertet, mit der man sich dank First-Class-Modules, praktischer Mutabilität und eines vorhersehbaren Code-Stils leichter auf die Implementierung konzentrieren kann
- Das Ökosystem von Haskell ist größer, aber die Auswahl von Bibliotheken kann sich wie eine eigene Disziplin anfühlen, während in OCaml trotz kleinerem Umfang die nötigen Werkzeuge überraschend gut funktionieren
- Beide Sprachen sind kleiner als Mainstream-Sprachen und ihre Standardbibliotheken sind eher minimal, können aber für industrielle Anwendungen völlig ausreichen, solange man nicht stark von bestimmten SDKs abhängt
Ausgangspunkt des Vergleichs
- Die Grundlage sind 8 Jahre Nutzung von Haskell und 8 Monate Nutzung von OCaml in der Produktion
- Verglichen werden Syntax, Sprachfeatures, Ökosystem, Tools, Compiler-Meldungen und Standardbibliothek
- Beide Sprachen haben sich genug weiterentwickelt, um reale industrielle Anforderungen zu unterstützen, aber die aktuelle Präferenz geht eher in Richtung OCaml
Syntax: Haskell ist kompakter, aber auch OCaml hat die Vorteile der ML-Familie
- Mit Haskell lassen sich Ideen mit sehr wenigen Zeichen ausdrücken, was ein starkes Gefühl syntaktischer Eleganz vermittelt
- Auch OCaml ist als Sprache der ML-Familie hervorragend, aber Haskell bietet einen stärker impliziten (tacit) Stil
- Im Beispiel zum Aufsummieren von Zahlen in einem String drückt Haskell dies kurz als
sum . map read . wordsaus, während OCaml per Pipeline das Aufteilen, Umwandeln und Falten des Strings explizit beschreibt - Die Definition eines Binärbaum-Typs drückt in beiden Sprachen algebraische Datentypen natürlich aus
- Beim Parsing-Beispiel nutzen beide Sprachen Pattern Matching und Option-Werte, aber Haskell verwendet do-Notation und
guard, OCaml dagegenOption.bindund explizitesmatch
Features: Haskell ist reichhaltiger, OCaml weniger zerstreuend
- Haskell hat sehr viele Features, so viele, dass sich als Vergleich eher C++ aufdrängt
- Diese vielen Features sind Werkzeuge, um Probleme sehr präzise zu lösen, können aber schon vor der eigentlichen Implementierung dazu führen, dass man über den Lösungsansatz selbst grübelt
- In Haskell verliert man sich leicht in Designentscheidungen rund um Optionen wie
TypeFamilies,DataKindsundGADTs - Ein schlechter Zustand in bestehenden OCaml-Projekten bedeutet meist fehlende Variablennamen, fehlende Dokumentation oder Funktionen mit mehr als 200 Zeilen und gilt damit noch als beherrschbar
- Dagegen kann man in bestehenden Haskell-Projekten auf Komplexität stoßen, auf die selbst 8 Jahre Erfahrung nicht vorbereiten
- Durch diesen Unterschied fühlt sich die Arbeit in OCaml produktiver an
-
Von beiden Sprachen geteilte Features
- Beide bieten eine ausdruckszentrierte Syntax, standardmäßige Immutabilität, Higher-Order Functions, anonyme Funktionen, algebraische Datentypen und Pattern Matching
- Parametrische Polymorphie, Type Inference, syntaktischen Zucker für Monaden, Garbage Collector, Multithreading und GADTs kann man ebenfalls in beiden nutzen
-
In Haskell stärker ausgeprägte Features
- Haskell bietet standardmäßige Reinheit, komponierbare Lazy Evaluation, Type Classes, Higher-Kinded Types und optionale Sprach-Erweiterungen
- Weil es so viele mächtige Features gibt, kann sich die Art der Abstraktion von Projekt zu Projekt stark unterscheiden
-
In OCaml stärker ausgeprägte Features
- OCaml bietet First-Class-Modules, polymorphe Varianten, Objekte, Klassen und Vererbung sowie leicht nutzbare Mutabilität
- Die Bandbreite der Features ist kleiner als bei Haskell, was den Vorteil hat, dass sich Codebasen leichter vorhersagen lassen
Ökosystem: Haskell ist größer, OCaml hat die nötigen Lösungen
- Beide Sprachen sind Nischen-Sprachen der funktionalen Programmierung, daher ist erstklassige Unterstützung für die neuesten Frameworks schwer zu erwarten
- Trotzdem gibt es für die meisten allgemeinen Aufgaben Lösungen, auch wenn man in manchen Fällen zusätzliche Custom Bindings schreiben muss
- Auch in OCaml findet man Pakete für die Praxis wie etwa:
- otoml: TOML-Parser
- Mint Tea: TUI-Framework
- ocaml-opentelemetry: OpenTelemetry-Instrumentierung
- awsm: OCaml-AWS-Client
- petrol: schnelle SQL-API für OCaml
- Das Haskell-Ökosystem bietet mehr Pakete und mehr sofort einsetzbare Lösungen
- Für die Stripe API gibt es in Haskell 13 Client-Bibliotheken, in OCaml nur 1, und diese OCaml-Bibliothek wurde zuletzt vor 8 Jahren geändert, also faktisch eher 0
- In Haskell muss man nach dem Finden einer Lösung zusätzlich noch beurteilen, welche Bibliothek man unter zu vielen Optionen wählen soll
- Die Auswahl von Bibliotheken wird teils wie eine eigene Fähigkeit behandelt, sodass es sogar Texte zur Bewertung von Bibliotheken gibt
- Neue Haskell-Bibliotheken entstehen oft nicht, um ein anderes Problem zu lösen, sondern weil jemand es mit einer anderen Abstraktion oder einem neuen Feature anders schreiben wollte
- Es kann interessanter sein, einen Logger mit Comonads zu entwerfen, als einen GitHub-API-Client zu bauen und viel JSON zu parsen
Tools: Haskell ist mächtig, aber schwankend, OCaml funktioniert einfach
- Haskell-Tools vereinen starke Vorteile mit Problemen bei der Nutzbarkeit
- Hoogle ist ein mächtiges Werkzeug, mit dem sich das gesamte Ökosystem allein über Typ-Signaturen durchsuchen lässt
- Gleichzeitig gibt es Probleme wie Fehlermeldungen von Build-Tools, Situationen, in denen bei einem funktionierenden Projekt kein Build-Plan gefunden wird, Re-Kompilierung der IDE nach Paketänderungen oder fehlende Dokumentation der Standardbibliothek für bestimmte Versionen
- Die Erfahrung mit Haskell-Tools schwankt zwischen Momenten, in denen man sich fragt, wie andere Sprachen ohne solche Werkzeuge überhaupt verwendet werden, und Momenten, in denen man sich fragt, wie Haskell-Nutzer mit der fehlenden grundlegenden Nutzbarkeit leben
- Bei OCaml überrascht eher, wie oft man trotz kleinerem Ökosystem Dinge findet, die einfach funktionieren
- Das LSP-basierte VSCode-OCaml-Plugin funktionierte ohne besondere Anpassungen und ohne Probleme
- Der Einstieg in die OCaml-Tooling-Welt ist vielleicht nicht maximal bequem, aber intuitiv, robust und funktioniert in den meisten Fällen zuverlässig
-
Tool-Vergleich
- Compiler: OCaml ist ocaml, Haskell ist ghc
- REPL: OCaml ist utop, Haskell ist ghci
- Build-Tools: OCaml ist dune, Haskell sind cabal und stack
- Paketmanager und Repository: OCaml ist opam, Haskell sind cabal und Hackage
- Linter: OCaml ist zanuda, Haskell ist hlint
- Formatter: OCaml ist ocamlformat und topiary, Haskell sind fourmolu, stylish-haskell, hindent, ormolu
- Typsuche und Codesuche: OCaml ist Sherlodoc und Sherlocode, Haskell sind Hoogle und Hackage Search
- Online-Playground und LSP: OCaml ist TryOCaml und ocaml-lsp, Haskell sind Haskell Playground und HLS
Compiler-Meldungen: Haskell ist wortreich, OCaml knapp
- In funktionalen Sprachen ist der Compiler ein zentrales Werkzeug, um zu verstehen, warum der Code die beabsichtigten Annahmen nicht erfüllt
- Deshalb sollten Fehlermeldungen die nötigen Informationen leicht zugänglich darstellen
- Compiler-Meldungen in Haskell enthalten viel Kontext und sind ausführlich, neigen aber auch zu redundanten oder zerstreuenden Informationen
- Compiler-Meldungen in OCaml sind recht knapp und manchmal sogar zu knapp
- Das Beispielprogramm mit Fehler versucht in Haskell per
x = 1 + [3, 1, 2]und in OCaml perlet x = 1 + [3; 1; 2]eine Ganzzahl mit einer Liste zu addieren
Standardbibliothek: Beide sind minimal, aber Haskell glänzt bei der Dokumentation
- Die Standardbibliothek prägt sowohl die ersten Programme in einer Sprache als auch die spätere Nutzungserfahrung
- Eine gute Standardbibliothek ist die Grundlage für den Erfolg einer Programmiersprache, während eine schwache Standardbibliothek endlose Debatten über alternative Standardbibliotheken auslösen kann
- Eine wünschenswerte Standardbibliothek sollte eher dem batteries-included-Ansatz folgen
- Zur gewünschten Ausstattung zählen ein Option-ähnlicher Typ, UTF-8-Strings, Map und HashMap, JSON- und XML-Parser sowie asynchrone Primitive
- Wer nicht erst den Bau von Build-Tools und Dependency-Tracking lernen will, braucht mehr Funktionalität in der Standardbibliothek
- Build Systems a la Carte analysiert den Bereich von Dependency Trackern und Build-Tools
- Sowohl Haskell als auch OCaml haben eine vergleichsweise minimale Standardbibliothek
- In Haskell fehlen Map und HashMap in der Standardbibliothek
- In OCaml fehlen non-empty lists und Bitraversable
- Die Haskell-Standardbibliothek ist
base, OCaml verwendet die OCaml standard library - Die Qualität der Haskell-Dokumentation ist teilweise so gut, dass selbst erfahrene Entwickler überrascht sind
- Zu den Stärken der Haskell-Dokumentation gehört auch die Möglichkeit, direkt zum Quellcode zu springen; für OCaml sei eine ähnliche Funktion wohl in Vorbereitung
-
Dokumentationsbeispiele
- Beispiele aus der Haskell-List-Dokumentation
- Beispiele aus der OCaml-List-Dokumentation
- Selbst bei Funktionen mit offensichtlichem Ergebnis vermitteln beispielzentrierte Dokumentationen sofort ein Gefühl dafür, wie sich eine API einsetzen lässt
Fazit: Beide taugen für den industriellen Einsatz, aber derzeit mit Präferenz für OCaml
- Beide Sprachen haben sich stark genug entwickelt, um reale industrielle Anforderungen zu unterstützen
- Im Vergleich zu Mainstream-Sprachen bleiben es dennoch eher kleine Sprachen
- Solange man nicht kritisch von der Existenz bestimmter SDKs abhängt, kann man mit beiden Sprachen die nächste Anwendung mit Freude entwickeln
- Derzeit wird OCaml als Sprache bewertet, mit der man sich leichter auf das tatsächliche Bauen von Dingen konzentrieren kann
Noch keine Kommentare.