Ist das Typensystem von Haskell ein Hindernis für das Verständnis der funktionalen Programmierung? [geschlossen]

33

Ich studiere Haskell, um die funktionale Programmierung zu verstehen, mit der Erwartung, dass ich die Erkenntnisse, die ich in anderen Sprachen erhalte, anwenden werde (hauptsächlich Groovy, Python, JavaScript).

Ich habe mich für Haskell entschieden, weil ich den Eindruck hatte, dass es sehr rein funktional ist und kein Vertrauen in den Staat zulässt.

Ich habe mich nicht für Haskell entschieden, weil ich an der Navigation in einem extrem starren Typensystem interessiert war.

Meine Frage lautet: Ist ein starkes Typsystem ein notwendiges Nebenprodukt einer extrem reinen funktionalen Sprache, oder handelt es sich hierbei um eine Design-Wahl, die nichts mit Haskell zu tun hat?

Eric Wilson
quelle
6
Wenn Sie nichts explizit eingeben möchten, müssen Sie nichts explizit eingeben. Haskell kann von sich aus sehr gut auf Typen schließen. Und es ist nicht so, dass eine einzelne Variable möglicherweise zwei inkompatible Typen speichert.
Anon.
4
@Anon ja, aber deine Listen müssen homogen sein. Vertrauen Sie mir, diese Art von Dingen kann Ihnen im Weg stehen, auch wenn Sie auf eine andere Schreibweise schließen.
Eric Wilson
13
@ FarmBoy und was ist mit der Verwendung von Vielleicht falsch? Java macht Sie wirklich dazu, Vielleicht in allen Klassen zu verwenden, was die seltsame Sache ist, die zu tun ist.
Alternative
3
Und wenn Sie wirklich eine heterogene Liste verwenden möchten, können Sie natürlich auch algebraische Datentypen verwenden.
Alternative
1
@mathepic an dieser stelle haben wir meine ursprüngliche frage wirklich aus den augen verloren, was eine vollkommen gültige frage war.
Eric Wilson

Antworten:

40

Ich glaube, dass das Verständnis von Haskells Typsystem ein Verstärker für das Verständnis der funktionalen Programmierung ist.

Die Sache mit der rein funktionalen Programmierung ist, dass ohne Nebenwirkungen, mit denen Sie alle möglichen Dinge implizit ausführen können, die Struktur Ihrer Programme durch die rein funktionale Programmierung viel deutlicher wird.

Haskell hindert Sie daran, Dinge unter den Teppich zu schieben, zwingt Sie, sich explizit mit der Struktur Ihres Programms zu befassen, und bringt Ihnen eine Sprache bei, die diese Strukturen beschreibt: die Sprache der Typen. Das Verstehen von Typen, insbesondere von umfangreichen Typen wie Haskell, macht Sie zu einem besseren Programmierer in jeder Sprache.

Wenn Haskell nicht stark typisiert wäre, wären Konzepte wie Monaden, anwendbare Funktoren und dergleichen niemals auf die Programmierung angewendet worden.

Waquo
quelle
2
Dies ist eine gute Antwort. Obwohl das Typensystem auf den ersten Blick ungewöhnlich erscheint, werden Sie später beim Erlernen der fortgeschritteneren Konzepte feststellen, dass es bestimmte Dinge gibt, die nur aufgrund der Einhaltung dieses Typs möglich sind System (STM und Data Parallel zur obigen Liste hinzufügen). Dinge, die in anderen Systemen keine Anfänger wären, passen natürlich zum Haskell-System. Mein Rat: bleiben Sie eine Weile dabei, lassen Sie es im Laufe der Zeit einwirken (es ist keine "vollgestopfte" Sprache).
Anon
2
Ich weiß, dass dies eine super alte Antwort ist, aber ich bin eigentlich anderer Meinung. Ich denke, dass das Typensystem, so explizit einige Dinge in der Sprache auch sein mögen, insbesondere bei Monaden wie State und Parsec eine TONNE von Dingen unter den Teppich kehren kann. Dies beeinträchtigt meine Fähigkeit, die Bibliotheken der Sprache zu lernen, sehr.
Savanni D'Gerinel
4
@ SavanniD'Gerinel: Ich denke in dieser Antwort bedeutet "Dinge unter den Teppich schieben" nicht, implizite Funktionen hinzuzufügen (was Haskell auf kontrollierte Weise tut, z. B. durch Monaden, und was hilft, das Boilerplate zu reduzieren), sondern etwas Code zuzulassen etwas tun, was nicht erwartet wird. ZB: Eine reine Funktion in Haskell wird niemals Nebenwirkungen haben. Zeitraum. In vielen anderen Sprachen können Sie dies in der Dokumentation einer Funktion versprechen, aber nichts in Ihrer Sprache hindert Sie daran, einige Nebenwirkungen irgendwo in Ihrem Code einzuschleusen.
Giorgio
33

Die am dynamischsten typisierte funktionale Sprache ist wohl Scheme. Das heißt, Haskells Typensystem ist ein Indikator für seine Reinheit. Es geht um die Frage "Wie misst man Reinheit?". Mit dem Typensystem von Haskell können Sie unreine Vorgänge auf einfache Weise absperren IO. Dazu benötigen Sie ein statisches Typsystem.

Nehmen wir an, das Typensystem von Haskell hat nichts mit funktionaler Programmierung zu tun. Es wäre immer noch ein Hochkonjunktur, zu behaupten, dass das Typensystem Ihnen bei diesem pädagogischen Unterfangen nicht helfen würde. Das Typensystem von Haskell ist umfangreich und komplex und umso interessanter im Vergleich zu den Typensystemen von C ++ und OCaml.

Ist es ein Hindernis? Nein, ich denke es ist eine Bereicherung. Versuchen Sie zu überlegen, wie Sie mit Haskells Faulheit umgehen sollen, ohne IOzum Beispiel.

Logan Capaldo
quelle
8
+1 Haskells Typensystem kann dein Freund sein, sobald du dich daran gewöhnt hast.
Larry Coleman
Msgstr "Dazu benötigen Sie ein statisches Typensystem". "Ja wirklich?"
Jon Harrop
1
"umso interessanter im Vergleich zu den Typsystemen von C ++ und OCaml". Haben Sie sich mit OCamls erstklassigen Modulen höherer Ordnung und strukturell typisierten abgeleiteten Objektsystemen und polymorphen Varianten befasst?
Jon Harrop
2
@JonHarrop oder ein Effektsystem oder eine Methode zum Messen / Bewerten der Reinheit. Ja, deshalb ist es interessant, sie zu vergleichen. Unterschiedliche Auswahlmöglichkeiten ergeben unterschiedliche Sprachen.
Logan Capaldo
20

Clojure ist dynamisch geschrieben und fast so rein wie Haskell. Es gibt also ein gutes Argument dafür, dass das Typensystem von Haskell eher eine Designentscheidung als eine absolute Anforderung war. Beide haben definitiv ihre Stärken, also sollten Sie Clojure in Betracht ziehen, wenn Sie Haskells Starrheit wirklich nicht mögen (siehe unten).

Als ich anfing, Haskell zu verwenden, empfand ich das Typensystem als störend und tolerierte es nur wegen der Typinferenz. Ich stellte bald fest, dass viele der vom Compiler beklagten Tippfehler ohnehin nicht funktionierten, selbst wenn der Compiler sie mir überlassen hätte (z. B. versehentlich map anstelle von concatMap verwenden). Dann stellte ich fest, dass Programme, die die Typprüfung bestanden hatten, normalerweise korrekt oder zumindest nahezu korrekt waren. Ich hatte sogar eine träge Phase, in der ich ein Refactoring durchgeführt habe, indem ich einen Funktionstyp geändert und den Compiler sagen ließ, was noch geändert werden musste. Schließlich wurde mir klar, dass Haskells Schriftsystem tatsächlich sehr aussagekräftig war, und ich begann, meine Programme mit Schriften zu gestalten. Das ist der Heilige Gral von Haskell.

Larry Coleman
quelle
Noch etwas zu beachten: Ich habe das funktionale Programmieren mit Scheme und Haskell ungefähr zur gleichen Zeit gelernt (erstere für eine Klasse und letztere zum Spaß). Ich fand heraus, dass das Verstehen der Rekursion mit Haskells Pattern-Matching viel einfacher war als mit ifs und conds in Scheme, was sich meiner Meinung nach auch auf Clojure überträgt.
Tikhon Jelvis
@ Larry Coleman: +1 für die genaue Beschreibung meiner eigenen Erfahrung mit Typensystemen: zuerst C ++, dann Ocaml und jetzt meine eigene Sprache Felix. Ja, ich überarbeite immer noch, indem ich Compiler-Fehler jage.
Yttrill
8

Das Typensystem von Haskell ist der Schlüssel für die Fähigkeit, Effekte von reinem Code zu isolieren. Wenn Sie Effekte nicht auf andere Weise isolieren oder vollständig entfernen können, ist ein starkes statisches Typsystem eine Voraussetzung für reine Funktionsprogrammierung.

Haskell ist ein sehr gutes Beispiel für eine Sprache mit einem starken statischen Typensystem. Wenn Sie eine breite und umfassende Ausbildung in Informatik und insbesondere in der Gestaltung von Programmiersprachen wünschen, ist Haskell eine ausgezeichnete Wahl für eine der Sprachen, die Sie lernen sollten.

Das Typensystem sollte kein großes Hindernis sein. Menschen, die programmieren, befolgen selbst bei der Verwendung dynamischer Sprachen in der Regel Typisierungskonventionen, die mit dem Haskell-Typensystem codiert werden können. Haskell bietet auch eine Typinferenz, die die Ausführlichkeit im Vergleich zu Sprachen wie C ++ und Java verringert. Wenn Sie eine Fehlermeldung erhalten, teilt Ihnen der Compiler nur zur Kompilierungszeit mit, was eine Sprache mit dynamischen Typen Ihnen zur Laufzeit mitteilen würde.

Das Gegenteil eines dynamischen Typsystems ist ein statisches Typsystem, kein starkes Typsystem. Ein starkes Typensystem ist das Gegenteil eines schwachen Typensystems.

dan_waterworth
quelle
1
Zum Beispiel ist C statisch, aber schwach typisiert. Sie haben Typen, aber es ist einfach, das Typensystem vollständig zu unterwandern, mit den zugrunde liegenden maschinenspezifischen Darstellungen herumzuspielen usw. Viele dynamisch typisierte Sprachen OTOH sind ziemlich stark typisiert - wenige implizite Umwandlungen, wenige Möglichkeiten (falls vorhanden), das Typensystem zu unterwandern.
Steve314
4

Es sagt Ihnen sofort, wenn Sie dumme Fehler machen. Das ist hilfreich. Ich habe in diesem letzten Semester in Racket (Schema) gearbeitet, und es gab einige Male, in denen ich einen nicht analysierten s-exp bestanden habe, bei dem ich einen analysierten ast für eine Funktion in meinem Interpreter erwartet habe, und er erschien nur in meinem mittelgroße Testsuite. Wenn ich statisch getippt hätte, wäre ich sofort darauf aufmerksam geworden.

Natürlich können logische Fehler nicht wirklich vom Typensystem erfasst werden, aber die Anzahl der Möglichkeiten, wie Sie Fehler machen können, ist erheblich verringert.

Wenn Sie möchten, können Sie das Typensystem auch über die Typinferenz ignorieren. Es ist immer noch da, aber es erfordert keinen aktiven Input von Ihrer Seite. Es ist immer noch hilfreich, die Arten Ihrer Funktionen zu verstehen, aber der richtige Code wird gut funktionieren.

Die Reinheit von Haskell ist in seinem Typensystem kodiert. Die E / A-Monade ist ein Konstrukt auf Typebene, das verhindert, dass unreiner Code in reine Funktionen gelangt, sodass die Reinheit durch das Typsystem garantiert wird.

Theo Belaire
quelle
8
Wenn Sie denken, Sie können Haskells Typensystem ignorieren, dann haben Sie vermutlich nicht viel Haskell codiert.
Eric Wilson
Ignorieren Sie die Funktion nicht so sehr, sondern tippen Sie sie ein, laden Sie sie in GHCi und starten Sie sie. Aber manchmal müssen Sie noch einige von Integral oder andere Funktionen einarbeiten.
Theo Belaire
1
Trotz der Typinferenz bringen 90% der Verwendung und Codierung von Haskell-Funktionen die verdammten Dinge ineinander, was ein Verständnis des Typensystems und der arkanen Typenkontrollfehlermeldungen voraussetzt. Sogar ": t" ist keine magische Lösung, sondern nur der erste Schritt, um zu verstehen, wie das Programm kompiliert werden kann.
Andres F.
Nun, einige Teile sind chaotisch, da stimme ich zu. Ich denke wirklich, dass das numerische Zeug im Vorspiel aufgeräumt und repariert werden könnte, denn so wie es aussieht, ist es ein schreckliches Durcheinander. Die meisten wichtigen funktionalen Aspekte sind jedoch ziemlich sauber. map, filter, foldr / l und andere spaßige funktionale funktionen funktionieren ganz gut.
Theo Belaire
2

Als "funktionale" Sprache bedeutet dies (neben anderen Dingen), dass Funktionen erstklassige Objekte in der Sprache sind.

Eine "reine" Sprache zu sein bedeutet, dass Funktionen mathematische Funktionen sind (im Gegensatz zu Prozeduren) - bei gleicher Eingabe erzeugen sie immer die gleiche Ausgabe.

Eine "reine Funktionssprache" ist eine Sprache, in der beide oben genannten Aussagen zutreffen. Ich bin mir nicht bewusst eine „rein- ly funktionalen Sprache“.

Ein starkes Typensystem ist eine saubere Möglichkeit, eine reine und dennoch praktische Sprache zu haben. Die Typen helfen dem Compiler, Optimierungen herauszufinden, abgesehen davon, um die Korrektheit weiter zu gewährleisten. (Aber das ist nicht der einzige Weg - Clojure ist rein, hat aber kein so starkes Typensystem wie Haskell.)

Wenn Sie das Typsystem stört, empfehle ich Ihnen, eine dynamischere Sprache wie Scheme zu verwenden oder Haskells Typinferenzsystem zu verwenden.

pyNem
quelle
0

Ja, das Typensystem ist eine unglaubliche Bereicherung. Es wäre sehr schwierig zu beschreiben, wie Monaden funktionieren oder wie einige Kombinatoren ohne das Typsystem arbeiten. Überlegen Sie, wie viele Tutorials in Haskell Sie zuerst auffordern, den Typ der betreffenden Funktion mit einem: t an der REPL zu prüfen. Das steht Ihnen in einer dynamisch getippten Sprache einfach nicht zur Verfügung. Klar, die ganze Komplexität des Typensystems ist noch da. Eine Monade ist immer noch eine Monade. Aber die Sprache hat beschlossen, sich die Hände zu waschen und überhaupt keine Hilfe zu leisten. Du bist auf dich allein gestellt, Kumpel. Ich klopfe nicht an dynamisch getippte Sprachen. Ich liebe sie sehr. Schema ist ein Elektrowerkzeug schlechthin. Sie werden jedoch feststellen, dass wir häufig eine Notation erfinden , wenn wir über Dinge wie Monaden in dynamischen Sprachen sprechenzur Beschreibung der Verfahrensarten. Ein funktionaler Programmierer kämpft auf die eine oder andere Weise mit Typen. Haskells Typprüfung gibt Ihnen nur gute Werkzeuge, um zu lernen, wie man das macht.

Ara Vartanian
quelle