Ich werde einen Kurs der unteren Abteilung in diskreten Strukturen unterrichten. Ich habe das Lehrbuch Diskrete Strukturen, Logik und Berechenbarkeit teilweise ausgewählt, weil es Beispiele und Konzepte enthält, die der Implementierung mit einer funktionalen Programmiersprache förderlich sind. (Ich denke auch, dass es ein gutes Lehrbuch ist.)
Ich möchte eine leicht verständliche FP-Sprache, um DS-Konzepte zu veranschaulichen und die die Schüler verwenden können. Die meisten Studenten hatten bestenfalls ein oder zwei Semester Programmierzeit in Java. Nachdem ich mir Scheme, Erlang, Haskell, Ocaml und SML angesehen habe, habe ich mich entweder für Haskell oder Standard ML entschieden. Ich neige mich aus den unten genannten Gründen zu Haskell, aber ich würde gerne die Meinung derer hören, die in dem einen oder anderen Programmierer aktiv sind.
- Sowohl Haskell als auch SML verfügen über einen Mustervergleich, der die Beschreibung eines rekursiven Algorithmus zum Kinderspiel macht.
- Haskell hat ein gutes Listenverständnis, das gut zu der Art und Weise passt, wie solche Listen mathematisch ausgedrückt werden.
- Haskell hat eine faule Bewertung. Hervorragend geeignet zum Erstellen von unendlichen Listen mithilfe der Listenverständnis-Technik.
- SML verfügt über einen wirklich interaktiven Interpreter, in dem Funktionen sowohl definiert als auch verwendet werden können. In Haskell müssen Funktionen in einer separaten Datei definiert und kompiliert werden, bevor sie in der interaktiven Shell verwendet werden.
- SML gibt eine explizite Bestätigung des Funktionsarguments und der Rückgabetypen in einer leicht verständlichen Syntax. Zum Beispiel: val foo = fn: int * int -> int. Haskells implizite Curry-Syntax ist etwas stumpfer, aber nicht völlig fremd. Zum Beispiel: foo :: Int -> Int -> Int.
- Haskell verwendet standardmäßig Ganzzahlen mit beliebiger Genauigkeit. Es ist eine externe Bibliothek in SML / NJ. Und SML / NJ schneidet die Ausgabe standardmäßig auf 70 Zeichen ab.
- Die Lambda-Syntax von Haskell ist subtil - sie verwendet einen einzelnen Backslash. SML ist expliziter. Ich bin mir nicht sicher, ob wir jemals Lambda in dieser Klasse brauchen werden.
Im Wesentlichen sind SML und Haskell ungefähr gleichwertig. Ich neige mich zu Haskell, weil ich das Listenverständnis und die unendlichen Listen in Haskell liebe. Ich mache mir jedoch Sorgen, dass die große Anzahl von Symbolen in Haskells kompakter Syntax den Schülern Probleme bereiten könnte. Nach dem, was ich beim Lesen anderer Beiträge auf SO gesammelt habe, wird Haskell nicht für Anfänger empfohlen, die mit FP beginnen. Wir werden jedoch keine vollwertigen Anwendungen erstellen, sondern nur einfache Algorithmen ausprobieren.
Was denken Sie?
Bearbeiten: Nachdem ich einige Ihrer großartigen Antworten gelesen habe, sollte ich einige meiner Stichpunkte klarstellen.
In SML gibt es keine syntaktische Unterscheidung zwischen der Definition einer Funktion im Interpreter und der Definition in einer externen Datei. Angenommen, Sie möchten die Fakultätsfunktion schreiben. In Haskell können Sie diese Definition in eine Datei einfügen und in GHCi laden:
fac 0 = 1
fac n = n * fac (n-1)
Für mich ist das klar, prägnant und entspricht der mathematischen Definition im Buch. Wenn Sie die Funktion jedoch direkt in GHCi schreiben möchten, müssen Sie eine andere Syntax verwenden:
let fac 0 = 1; fac n = n * fac (n-1)
Bei der Arbeit mit interaktiven Dolmetschern ist es aus Unterrichtssicht sehr, sehr praktisch, wenn der Schüler denselben Code sowohl in einer Datei als auch in der Befehlszeile verwenden kann.
Mit "expliziter Bestätigung der Funktion" meinte ich, dass SML Ihnen beim Definieren der Funktion sofort den Namen der Funktion, die Typen der Argumente und den Rückgabetyp mitteilt. In Haskell müssen Sie den :type
Befehl verwenden und erhalten dann die etwas verwirrende Curry-Notation.
Noch eine coole Sache über Haskell - dies ist eine gültige Funktionsdefinition:
fac 0 = 1
fac (n+1) = (n+1) * fac n
Dies entspricht wiederum einer Definition, die sie möglicherweise im Lehrbuch finden. Das geht in SML nicht!
quelle
Antworten:
So sehr ich Haskell liebe, hier sind die Gründe, warum ich SML für eine Klasse in diskreten Mathematik- und Datenstrukturen (und die meisten anderen Anfängerklassen) bevorzugen würde:
Zeit- und Raumkosten von Haskell-Programmen können selbst für Experten sehr schwer vorherzusagen sein. SML bietet viel eingeschränktere Möglichkeiten, die Maschine zu blasen.
Die Syntax für die Funktionsdefinition in einem interaktiven Interpreter ist identisch mit der in einer Datei verwendeten Syntax, sodass Sie sie ausschneiden und einfügen können.
Das Überladen von Bedienern in SML ist zwar völlig falsch, aber auch einfach. Es wird schwierig sein, eine ganze Klasse in Haskell zu unterrichten, ohne in Typklassen einsteigen zu müssen.
Der Schüler kann mit debuggen
print
. (Obwohl, wie ein Kommentator betont, es möglich ist, mit Haskell fast den gleichen Effekt zu erzielenDebug.Trace.trace
.)Unendliche Datenstrukturen beeindrucken die Menschen. Für Anfänger ist es besser, wenn sie einen Stream-Typ mit Ref-Zellen und Thunks definieren, damit sie wissen, wie es funktioniert:
datatype 'a thunk_contents = UNEVALUATED of unit -> 'a | VALUE of 'a type 'a thunk = 'a thunk_contents ref val delay : (unit -> 'a) -> 'a thunk val force : 'a thunk -> 'a
Jetzt ist es keine Magie mehr und Sie können von hier aus zu Streams (unendlichen Listen) gehen.
Das Layout ist nicht so einfach wie in Python und kann verwirrend sein.
Es gibt zwei Stellen, an denen Haskell einen Vorteil hat:
In Core Haskell können Sie die Typensignatur einer Funktion unmittelbar vor ihrer Definition schreiben. Dies ist sehr hilfreich für Studenten und andere Anfänger. Es gibt einfach keine gute Möglichkeit, mit Typensignaturen in SML umzugehen.
Haskell hat eine bessere konkrete Syntax. Die Haskell-Syntax ist eine wesentliche Verbesserung gegenüber der ML-Syntax. Ich habe eine kurze Notiz darüber geschrieben, wann Klammern in einem ML-Programm verwendet werden sollen . das hilft ein wenig.
Schließlich gibt es ein Schwert, das in beide Richtungen schneidet:
do
Notation erklären ,return
was verwirrend ist.Zu einem verwandten Thema finden Sie hier einige Ratschläge für Ihre Kursvorbereitung : Übersehen Sie nicht die rein funktionalen Datenstrukturen von Chris Okasaki. Auch wenn Ihre Schüler es nicht verwenden, möchten Sie auf jeden Fall eine Kopie haben.
quelle
Debug.Trace.trace :: String -> a -> a
undDebug.Trace.traceShow :: (Show a) => a -> b -> b
verfügbare, die die Einschränkungen von IO () umgehen und den Trace eifrig ausgeben.let
s).Wir unterrichten Haskell in den ersten Jahren an unserer Universität. Meine Gefühle dazu sind etwas gemischt. Einerseits bedeutet das Unterrichten von Haskell in den ersten Jahren, dass sie den imperativen Stil nicht verlernen müssen. Haskell kann auch sehr präzisen Code erstellen, den Leute, die zuvor Java hatten, schätzen können.
Einige Probleme, die mir bei Schülern häufig aufgefallen sind:
Der Mustervergleich kann zunächst etwas schwierig sein. Die Schüler hatten anfangs einige Probleme zu sehen, wie Wertekonstruktion und Mustervergleich zusammenhängen. Sie hatten auch einige Probleme bei der Unterscheidung zwischen Abstraktionen. Unsere Übungen umfassten Schreibfunktionen, die den arithmetischen Ausdruck vereinfachen, und einige Schüler hatten Schwierigkeiten, den Unterschied zwischen der abstrakten Darstellung (z. B.
Const 1
) und der metasprachlichen Darstellung (1
) zu erkennen.Wenn Ihre Schüler Listenverarbeitungsfunktionen selbst schreiben sollen, müssen Sie außerdem auf den Unterschied zwischen den Mustern hinweisen
[] [x] (x:xs) [x:xs]
Abhängig davon, wie viel funktionale Programmierung Sie ihnen unterwegs beibringen möchten, können Sie ihnen nur ein paar Bibliotheksfunktionen geben und sie damit herumspielen lassen.
Wir haben unseren Schülern keine anonymen Funktionen beigebracht, sondern ihnen lediglich
where
Klauseln erzählt . Für einige Aufgaben war dies etwas ausführlich, funktionierte aber ansonsten gut. Wir haben ihnen auch nichts über Teilanträge erzählt; Dies ist in Haskell wahrscheinlich recht einfach zu erklären (aufgrund seiner Schreibweise), daher könnte es sich lohnen, es ihnen zu zeigen.Sie entdeckte schnell Listenkomprehensionen und bevorzugt sie über Funktionen höherer Ordnung wie
filter
,map
,zipWith
.Ich denke, wir haben es ein bisschen versäumt, ihnen beizubringen, wie sie ihre Gedanken nach Typen führen können. Ich bin mir jedoch nicht ganz sicher, ob dies für Anfänger hilfreich ist oder nicht.
Fehlermeldungen sind für Anfänger normalerweise nicht sehr hilfreich. Sie benötigen gelegentlich Hilfe. Ich habe es selbst nicht ausprobiert, aber es gibt einen Haskell-Compiler, der speziell auf Neulinge ausgerichtet ist, hauptsächlich durch bessere Fehlermeldungen: Helium
Für die kleinen Programme waren Dinge wie mögliche Platzlecks kein Problem.
Insgesamt ist Haskell eine gute Unterrichtssprache, aber es gibt einige Fallstricke. Angesichts der Tatsache, dass sich die Schüler mit Listenverständnissen viel wohler fühlen als mit Funktionen höherer Ordnung, ist dies möglicherweise das Argument, das Sie benötigen. Ich weiß nicht, wie lange Ihr Kurs dauert oder wie viel Programmierung Sie ihnen beibringen möchten, aber planen Sie etwas Zeit ein, um ihnen grundlegende Konzepte beizubringen - sie werden es brauchen.
quelle
(x:xs)
stimmt mit einer nicht leeren Liste überein, dh das Argument muss einen Typ haben[a]
.[x:xs]
Entspricht einer Singleton-Liste, die eine nicht leere Liste enthält, dh das Argument muss einen Typ haben[[a]]
.[x:xs]
ist das gleiche wie[(x:xs)]
das ist das gleiche wie((x:xs):[])
.Übrigens,
Ist ungenau. Verwenden Sie GHCi:
Prelude> let f x = x ^ 2 Prelude> f 7 49 Prelude> f 2 4
Es gibt auch gute Ressourcen für Haskell in der Bildung auf der haskell.org edu. Seite, mit Erfahrungen von verschiedenen Lehrern. http://haskell.org/haskellwiki/Haskell_in_education
Schließlich können Sie ihnen Multicore-Parallelität nur zum Spaß beibringen, wenn Sie Haskell verwenden :-)
quelle
Viele Universitäten unterrichten Haskell als erste funktionale Sprache oder sogar als erste Programmiersprache, daher denke ich nicht, dass dies ein Problem sein wird.
Nachdem ich einen Teil des Unterrichts in einem solchen Kurs absolviert habe, stimme ich nicht zu, dass die möglichen Verwirrungen, die Sie identifizieren, so wahrscheinlich sind. Die wahrscheinlichsten Ursachen für frühe Verwirrung sind Analysefehler, die durch ein schlechtes Layout verursacht werden, und mysteriöse Meldungen über Typklassen, wenn numerische Literale falsch verwendet werden.
Ich würde auch keinem Vorschlag zustimmen, dass Haskell nicht für Anfänger empfohlen wird, die mit FP beginnen. Es ist sicherlich der Urknall-Ansatz in einer Weise, wie es strenge Sprachen mit Mutation nicht sind, aber ich denke, das ist ein sehr gültiger Ansatz.
quelle
Während Umarmungen diese Einschränkung haben können, tut GHCi nicht:
$ ghci GHCi, version 6.10.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer ... linking ... done. Loading package base ... linking ... done. Prelude> let hello name = "Hello, " ++ name Prelude> hello "Barry" "Hello, Barry"
Es gibt viele Gründe, warum ich GHC (i) gegenüber Umarmungen bevorzuge. Dies ist nur einer davon.
SML hat auch die sogenannte "implizite Curry" -Syntax.
$ sml Standard ML of New Jersey v110.69 [built: Fri Mar 13 16:02:47 2009] - fun add x y = x + y; val add = fn : int -> int -> int
Ich benutze Haskell viel lieber als SML, aber ich würde immer noch zuerst SML unterrichten.
'a
gegen''a
Unterscheidung in SML ist hart genug.quelle
Die meisten Antworten waren technisch, aber ich denke, Sie sollten mindestens eine in Betracht ziehen, die nicht so ist: Haskell (als OCaml) hat derzeit eine größere Community, die sie in einem breiteren Spektrum von Kontexten verwendet. Es gibt auch eine große Datenbank mit Bibliotheken und Anwendungen, die für Gewinn und Spaß bei Hackage geschrieben wurden . Dies kann ein wichtiger Faktor sein, damit einige Ihrer Schüler die Sprache nach Abschluss Ihres Kurses weiterhin verwenden und später möglicherweise andere funktionale Sprachen (wie Standard ML) ausprobieren.
quelle
Ich bin erstaunt, dass Sie OCaml und F # nicht in Betracht ziehen, da sie so viele Ihrer Bedenken ansprechen. Sicherlich haben anständige und hilfreiche Entwicklungsumgebungen für Lernende eine hohe Priorität? SML liegt weit zurück und F # ist in dieser Hinsicht allen anderen FPLs weit voraus.
Außerdem haben sowohl OCaml als auch F # Listenverständnisse.
quelle
Haskell. Ich bin in meiner Algen- / Theorieklasse in CS aufgrund der Dinge, die ich durch die Verwendung von Haskell gelernt habe, vorne. Es ist eine so umfassende Sprache, dass Sie eine Menge CS lernen, wenn Sie sie nur verwenden .
SML ist jedoch viel einfacher zu erlernen. Haskell verfügt über Funktionen wie verzögerte Bewertungs- und Kontrollstrukturen, die es viel leistungsfähiger machen, jedoch mit den Kosten einer steilen (ish) Lernkurve. SML hat keine solche Kurve.
Das heißt, der größte Teil von Haskell lernte Dinge aus weniger wissenschaftlichen / mathematischen Sprachen wie Ruby, ObjC oder Python.
quelle