Die Art und Weise, wie es mir gezeigt wurde, und was ich denke, nachdem ich einen Monat lang an Haskell gelernt habe, ist die Tatsache, dass funktionale Programmierung Ihr Gehirn auf interessante Weise verdreht: Es zwingt Sie, über vertraute Probleme auf unterschiedliche Weise nachzudenken : Denken Sie anstelle von Schleifen an Karten, Falten und Filter usw. Wenn Sie mehr als eine Perspektive auf ein Problem haben, können Sie im Allgemeinen besser über dieses Problem nachdenken und bei Bedarf die Ansicht wechseln.
Das andere wirklich nette an Haskell ist das Typensystem. Es ist streng typisiert, aber die Typinferenz-Engine lässt es sich wie ein Python-Programm anfühlen, das Ihnen auf magische Weise sagt, wenn Sie einen dummen typbezogenen Fehler gemacht haben. Haskells Fehlermeldungen in dieser Hinsicht fehlen etwas, aber wenn Sie sich mit der Sprache vertraut machen, werden Sie sich sagen: So soll das Tippen sein!
Dies ist das Beispiel, das mich überzeugt hat, Haskell zu lernen (und Junge, bin ich froh, dass ich es getan habe).
OK, es ist ein kurzes, lesbares Programm. In diesem Sinne ist es besser als ein C-Programm. Aber wie unterscheidet sich das von einem Python-Programm mit einer sehr ähnlichen Struktur?
Die Antwort ist faule Bewertung. In den meisten Sprachen (auch in einigen funktionalen) würde ein Programm wie das oben beschriebene dazu führen, dass die gesamte Datei in den Speicher geladen und dann unter einem neuen Namen erneut ausgeschrieben wird.
Haskell ist "faul". Es berechnet keine Dinge, bis es benötigt wird, und im weiteren Sinne berechnet es keine Dinge, die es nie benötigt. Wenn Sie beispielsweise die
writeFile
Zeile entfernen würden, würde Haskell sich überhaupt nicht darum kümmern, etwas aus der Datei zu lesen.So wie es ist, erkennt Haskell, dass das
writeFile
von dem abhängtreadFile
, und kann so diesen Datenpfad optimieren.Während die Ergebnisse vom Compiler abhängig sind, passiert normalerweise Folgendes, wenn Sie das obige Programm ausführen: Das Programm liest einen Block (z. B. 8 KB) der ersten Datei, schreibt ihn dann in die zweite Datei und liest dann einen weiteren Block aus der ersten Datei und schreibt es in die zweite Datei und so weiter. (Versuchen Sie es zu laufen
strace
!)... was sehr ähnlich aussieht wie die effiziente C-Implementierung einer Dateikopie.
Mit Haskell können Sie also kompakte, lesbare Programme schreiben - oft ohne viel Leistung zu verlieren.
Eine andere Sache, die ich hinzufügen muss, ist, dass Haskell es einfach schwierig macht, fehlerhafte Programme zu schreiben. Das erstaunliche Typsystem, das Fehlen von Nebenwirkungen und natürlich die Kompaktheit des Haskell-Codes reduzieren Fehler aus mindestens drei Gründen:
Besseres Programmdesign. Reduzierte Komplexität führt zu weniger Logikfehlern.
Kompakter Code. Es gibt weniger Zeilen, in denen Fehler vorhanden sind.
Fehler kompilieren. Viele Fehler sind einfach nicht gültig, Haskell .
Haskell ist nicht jedermanns Sache. Aber jeder sollte es versuchen.
quelle
hSetBuffering handle (BlockBuffering (Just bufferSize))
.Data.Bytestring.Lazy.readFile
), die nichts zu tun haben mit Haskell eine faule (nicht streng) Sprache. Monaden sequenzieren - dies bedeutet ungefähr "alle Nebenwirkungen sind erledigt, wenn Sie das Ergebnis herausnehmen". Was die "Lazy Bytestring" -Magie betrifft: Dies ist gefährlich, und Sie können dies mit einer ähnlichen oder einfacheren Syntax in den meisten anderen Sprachen tun.readFile
macht auch faul IO auf die gleiche WeiseData.ByteString.Lazy.readFile
. Die Antwort ist also nicht falsch und es handelt sich nicht nur um eine Compileroptimierung. Dies ist in der Tat Teil der Spezifikation für Haskell : "DiereadFile
Funktion liest eine Datei und gibt den Inhalt der Datei als Zeichenfolge zurück. Die Datei wird bei Bedarf wie bei träge gelesengetContents
."const fs = require('fs'); const [file1, file2] = process.argv.slice(2); fs.createReadStream(file1).pipe(fs.createWriteStream(file2))
. Bash hat auch etwas ähnliches:cat $1 > $2
Sie stellen die falsche Frage.
Haskell ist keine Sprache , wo man Blick auf ein paar coolen Beispiele geht und gehen „Aha, ich sehe jetzt, das ist , was es gut ist!“
Es ist eher so, als hätten wir all diese anderen Programmiersprachen und sie sind alle mehr oder weniger ähnlich, und dann gibt es Haskell, das völlig anders und verrückt ist, auf eine Weise, die total fantastisch ist, wenn man sich erst einmal an die Verrücktheit gewöhnt hat. Das Problem ist jedoch, dass es eine Weile dauert, bis man sich an die Verrücktheit gewöhnt hat. Dinge, die Haskell von fast jeder anderen Sprache unterscheiden:
sowie einige andere Aspekte, die sich von vielen gängigen Sprachen unterscheiden (aber von einigen geteilt werden):
Wie einige andere Poster geantwortet haben, bedeutet die Kombination all dieser Funktionen, dass Sie die Programmierung auf eine ganz andere Art und Weise betrachten. Daher ist es schwierig, ein Beispiel (oder eine Reihe von Beispielen) zu finden, das dies dem Joe-Mainstream-Programmierer angemessen vermittelt. Es ist eine experimentelle Sache. (Um eine Analogie zu ziehen, ich kann Ihnen Fotos von meiner Reise nach China 1970 zeigen, aber nachdem Sie die Fotos gesehen haben, werden Sie immer noch nicht wissen, wie es war, während dieser Zeit dort gelebt zu haben. Ebenso kann ich Ihnen einen Haskell zeigen 'quicksort', aber du wirst immer noch nicht wissen, was es bedeutet, ein Haskeller zu sein.)
quelle
Was Haskell wirklich auszeichnet, ist der Aufwand für die Durchsetzung der funktionalen Programmierung. Sie können in nahezu jeder Sprache in einem funktionalen Stil programmieren, aber es ist allzu einfach, auf den ersten Blick darauf zu verzichten. Haskell erlaubt es Ihnen nicht, die funktionale Programmierung aufzugeben, daher müssen Sie sie zu ihrer logischen Schlussfolgerung führen, die ein endgültiges Programm ist, über das man leichter nachdenken kann, und eine ganze Klasse der dornigsten Arten von Fehlern umgeht.
Wenn es darum geht, ein Programm für den realen Gebrauch zu schreiben, fehlt Haskell möglicherweise auf praktische Weise, aber Ihre endgültige Lösung ist besser, wenn Sie Haskell von Anfang an kennen. Ich bin definitiv noch nicht da, aber bisher war es viel aufschlussreicher, Haskell zu lernen, als zu sagen, Lisp war auf dem College.
quelle
unsafePerformIO
für Leute, die nur die Welt brennen sehen wollen;)Ein Teil der Aufregung ist, dass Reinheit und statische Typisierung Parallelität in Kombination mit aggressiven Optimierungen ermöglichen. Parallele Sprachen sind jetzt heiß, und Multicore ist etwas störend.
Haskell bietet Ihnen mehr Optionen für Parallelität als so ziemlich jede Allzwecksprache sowie einen schnellen, nativen Code-Compiler. Es gibt wirklich keine Konkurrenz mit dieser Art der Unterstützung für parallele Stile:
Wenn Sie also daran interessiert sind, dass Ihr Multicore funktioniert, hat Haskell etwas zu sagen. Ein guter Anfang ist das Tutorial von Simon Peyton Jones zur parallelen und gleichzeitigen Programmierung in Haskell .
quelle
Software Transactional Memory ist eine ziemlich coole Möglichkeit, mit Parallelität umzugehen. Es ist viel flexibler als das Weiterleiten von Nachrichten und nicht wie Mutexe anfällig für Deadlocks. Die Implementierung von STM durch GHC gilt als eine der besten.
quelle
Ich habe das letzte Jahr damit verbracht, Haskell zu lernen und ein ziemlich großes und komplexes Projekt darin zu schreiben. (Das Projekt ist ein automatisiertes Optionshandelssystem, und alles, von den Handelsalgorithmen bis zum Parsen und Verarbeiten von Marktdaten-Feeds auf niedriger Ebene und hoher Geschwindigkeit, wird in Haskell durchgeführt.) Es ist wesentlich präziser und verständlicher (für diejenigen mit angemessener Hintergrund) als eine Java-Version wäre, sowie extrem robust.
Möglicherweise war der größte Gewinn für mich die Fähigkeit, den Kontrollfluss durch Dinge wie Monoide, Monaden usw. zu modularisieren. Ein sehr einfaches Beispiel wäre das Bestellmonoid; in einem Ausdruck wie
wo
c1
usw. RückkehrLT
,EQ
oderGT
,c1
zurückkehrEQ
Ursachen der Expression fortzusetzen, zu bewertenc2
; if gibtc2
zurückLT
oderGT
das ist der Wert des Ganzen undc3
wird nicht ausgewertet. Diese Art von Dingen wird in Dingen wie monadischen Nachrichtengeneratoren und Parsern, in denen ich verschiedene Arten von Zuständen herumtrage, unterschiedliche Abbruchbedingungen habe oder für einen bestimmten Anruf entscheiden möchte, ob Abbruch wirklich bedeutet, erheblich komplexer und komplexer "keine weitere Verarbeitung" oder bedeutet "am Ende einen Fehler zurückgeben, aber die Verarbeitung fortsetzen, um weitere Fehlermeldungen zu sammeln".Dies alles ist etwas, das einige Zeit und wahrscheinlich einige Mühe braucht, um es zu lernen, und daher kann es für diejenigen, die diese Techniken noch nicht kennen, schwierig sein, ein überzeugendes Argument dafür zu liefern. Ich denke, dass das All About Monads- Tutorial eine ziemlich eindrucksvolle Demonstration einer Facette davon bietet, aber ich würde nicht erwarten, dass jemand, der nicht bereits mit dem Material vertraut ist, es beim ersten oder sogar beim dritten sorgfältigen Lesen "bekommt".
Wie auch immer, es gibt auch viele andere gute Sachen in Haskell, aber dies ist eine wichtige Sache, die ich nicht so oft erwähnt sehe, wahrscheinlich weil sie ziemlich komplex ist.
quelle
Ein interessantes Beispiel finden Sie unter: http://en.literateprograms.org/Quicksort_(Haskell)
Interessant ist es, die Implementierung in verschiedenen Sprachen zu betrachten.
Was Haskell zusammen mit anderen funktionalen Sprachen so interessant macht, ist die Tatsache, dass Sie anders über das Programmieren nachdenken müssen. Beispielsweise verwenden Sie im Allgemeinen keine for- oder while-Schleifen, sondern die Rekursion.
Wie oben erwähnt, zeichnen sich Haskell und andere funktionale Sprachen durch parallele Verarbeitungs- und Schreibanwendungen für die Arbeit mit mehreren Kernen aus.
quelle
Ich konnte Ihnen kein Beispiel geben, ich bin ein OCaml-Typ, aber wenn ich mich in einer Situation wie Ihnen befinde, greift die Neugier einfach und ich muss einen Compiler / Interpreter herunterladen und ausprobieren. Auf diese Weise lernen Sie wahrscheinlich viel mehr über die Stärken und Schwächen einer bestimmten funktionalen Sprache.
quelle
Eine Sache, die ich beim Umgang mit Algorithmen oder mathematischen Problemen sehr cool finde, ist Haskells inhärente träge Bewertung von Berechnungen, die nur aufgrund ihrer strengen funktionalen Natur möglich ist.
Wenn Sie beispielsweise alle Primzahlen berechnen möchten, können Sie verwenden
und das Ergebnis ist tatsächlich eine unendliche Liste. Aber Haskell wird es von links nach rechts auswerten. Solange Sie nicht versuchen, etwas zu tun, das die gesamte Liste erfordert, können Sie es trotzdem verwenden, ohne dass das Programm im Unendlichen hängen bleibt, wie zum Beispiel:
Das summiert alle Primzahlen unter 100. Das ist aus mehreren Gründen schön. Zuerst muss ich nur eine Primfunktion schreiben, die alle Primzahlen generiert, und dann bin ich ziemlich bereit, mit Primzahlen zu arbeiten. In einer objektorientierten Programmiersprache müsste ich der Funktion mitteilen, wie viele Primzahlen vor der Rückkehr berechnet werden sollen, oder das Verhalten einer unendlichen Liste mit einem Objekt emulieren. Eine andere Sache ist, dass Sie im Allgemeinen Code schreiben, der ausdrückt, was Sie berechnen möchten und nicht in welcher Reihenfolge die Dinge bewertet werden sollen - stattdessen erledigt der Compiler dies für Sie.
Dies ist nicht nur für unendliche Listen nützlich, sondern wird auch verwendet, ohne dass Sie es ständig wissen, wenn nicht mehr als nötig ausgewertet werden muss.
quelle
Ich stimme anderen zu, dass es nicht der beste Weg ist, Haskell zu zeigen, wenn man ein paar kleine Beispiele sieht. Aber ich werde trotzdem welche geben. Hier ist eine blitzschnelle Lösung für die Probleme 18 und 67 des Euler-Projekts , bei der Sie aufgefordert werden, den Pfad mit der maximalen Summe von der Basis bis zur Spitze eines Dreiecks zu finden:
Hier ist eine vollständige, wiederverwendbare Implementierung des BubbleSearch- Algorithmus von Lesh und Mitzenmacher. Ich habe damit große Mediendateien für die Archivierung auf DVD ohne Verschwendung gepackt:
Ich bin sicher, dieser Code sieht aus wie zufälliger Kauderwelsch. Wenn Sie jedoch Mitzenmachers Blogeintrag lesen und den Algorithmus verstehen, werden Sie erstaunt sein, dass es möglich ist, den Algorithmus in Code zu packen, ohne etwas über das zu sagen, wonach Sie suchen.
Nachdem ich Ihnen einige Beispiele gegeben habe, nach denen Sie gefragt haben, werde ich sagen, dass der beste Weg, um Haskell zu schätzen, darin besteht, das Papier zu lesen, das mir die Ideen gab, die ich zum Schreiben des DVD-Packers brauchte: Warum funktionale Programmierung von John Hughes wichtig ist. Das Papier ist eigentlich älter als Haskell, aber es erklärt auf brillante Weise einige der Ideen, die Menschen wie Haskell ausmachen.
quelle
Für mich ist die Attraktion von Haskell das Versprechen der vom Compiler garantierten Korrektheit. Auch wenn es sich um reine Teile des Codes handelt.
Ich habe viel wissenschaftlichen Simulationscode geschrieben und mich so oft gefragt , ob meine vorherigen Codes einen Fehler enthielten, der viele aktuelle Arbeiten ungültig machen könnte.
quelle
Ich finde, dass ich für bestimmte Aufgaben mit Haskell unglaublich produktiv bin.
Der Grund liegt in der prägnanten Syntax und der einfachen Prüfung.
So sieht die Syntax der Funktionsdeklaration aus:
Das ist der einfachste Weg, eine Funktion zu definieren.
Wenn ich das Gegenteil schreibe
Ich kann überprüfen, ob es für jede zufällige Eingabe eine Umkehrung ist, indem ich schreibe
Und von der Kommandozeile aus anrufen
Dadurch wird überprüft, ob alle Eigenschaften in meiner Datei gespeichert sind, indem die Eingaben hundertmal zufällig getestet werden.
Ich denke nicht, dass Haskell die perfekte Sprache für alles ist, aber wenn es darum geht, kleine Funktionen zu schreiben und zu testen, habe ich nichts Besseres gesehen. Wenn Ihre Programmierung eine mathematische Komponente hat, ist dies sehr wichtig.
quelle
Wenn Sie sich mit dem Typensystem in Haskell beschäftigen können, halte ich das für eine ziemliche Errungenschaft.
quelle
Es gibt keine Schleifenkonstrukte. Nicht viele Sprachen haben dieses Merkmal.
quelle
Ich stimme denen zu, die sagten, dass funktionale Programmierung Ihr Gehirn dazu bringt, die Programmierung aus einem anderen Blickwinkel zu betrachten. Ich habe es nur als Hobbyist benutzt, aber ich denke, es hat meine Herangehensweise an ein Problem grundlegend verändert. Ich glaube nicht, dass ich mit LINQ annähernd so effektiv gewesen wäre, ohne Haskell ausgesetzt gewesen zu sein (und Generatoren und Listenverständnisse in Python verwendet zu haben).
quelle
Um eine konträre Sichtweise zu äußern: Steve Yegge schreibt, dass Hindely-Milner-Sprachen nicht die Flexibilität haben, die erforderlich ist, um gute Systeme zu schreiben :
Haskell ist es wert, gelernt zu werden, aber es hat seine eigenen Schwächen.
quelle