Haskell lernen und aufkommende Fragen.



  • Guten Tag,

    ich versuche mich gerade an meiner ersten Programmiersprache und habe mir dazu das Buch "Haskell Intensivkurs" gekauft. Leider habe ich bei dem ersten Projekt schon einige Probleme und finde trotz mehrfachen lesens der entsprechenden Kapitel keine Lösung für meine Fragen. Es gibt zwei Module und damit die Fragen leichter zu verstehen sind, habe ich sie als Kommentare in den Code eingefügt. Gleichzeitig habe ich auch versucht, den Code zu erklären.

    Hier das erste Modul "modulWoerterbuch"

    module Woerterbuch(
         WBuch,
         leeresWBuch,
         einfuegen,
         finde
         loeschen) where
    -- Erstellung des ersten Moduls mit den entsprechenden Variablen. Es ist ein Modul pro Datei erlaubt.
    -- Durch "where" bleiben die weiteren Funktionen verborgen und können nicht direkt im Programm aufgerufen werden.
    
    newtype WBuch k v = D [(k,v)] deriving Show
    --"newtype" dient der Typensicherheit und der Typ erhält einen Datenkonstruktor "D". Allerdings würde hier in diesem
    --Beispiel auch "type" funktionieren, da es ja nur einen Typen gibt oder sehe ich das falsch?
    -- Nach "newtype" folgt der Typ "WBuch" mit dem Schlüsselwert "k" und dem Wert "v". D ist dann der Datenkonstruktor.
    -- Muss man aber "D" nicht wegen dem "newtype" sondern deswegen angeben, weil es sich hier um Tupel handelt?
    -- "deriving Show" dient zur Ausgabe vom "newtype" und Umwandlung in einen String. Ansonsten würde es bei einem Aufruf eine Fehlermeldung geben,
    -- dass das Show fehlt.
    
    leeresBuch :: Eq k=> WBuch k v
    leeresWBuch        = D []
    -- hier wird die Funktion "leeresBuch" definiert. Eq dient zum Vergleichen von Werten.
    -- Aber mit was wird denn verglichen? Es wird doch nur eine leere Liste erzeugt.
    
    einfuegen :: (k, v) -> WBuch k  v -> WBuch k v
    einfuegen x (D l) = D (x:l)
    --Die Funktion "einfuegen" erwartet drei Parameter, das "x" ist die Liste (k,v)
    -- der Wert "(D l)" ist vom Typ "WBuch". D steht für das Wörterbuch welches verwendet werden soll.
    -- Hier Frage ich mich aber generell bzw. verstehe nicht so richtig, wieso (D l) in der Signatur wie folgt steht: "WBuch k v".
    --l wird im Ergebnis ja zum Rest einer Liste. Nur was wird denn da drin stehen?
    -- Ich denke es ist aber wie so: "l" entspricht der Liste k und v. Das ist die Liste, wie sie vor dem Einfuegen
    -- existiert und diese Liste wird dann zum Rest der Liste, damit der Eintrag "x" keinen anderen Eintrag löscht und am Anfang der Liste steht.
    --das x steht für den Namen und die Adresse, die am Kopf der Liste eingetragen wird.
    -- Muss das "(D l)" eigendlich deswegen in Klammern, damit es als ein Wert in der Signatur beschrieben werden kann?
    
    finde :: Eq k => k -> WBuch k v -> Maybe v
    finde k (D l)     = lookup k l
    -- durch "Eq k" wird überprüft, ob sich der eingegebene Wert in der Liste "k" befindet.
    -- k ist der Parameter der übergeben werden muss. Es wird in der Liste "D" gesucht.
    -- wird in "k" nichts gefunden, dann wird der Wert "v" mit k verglichen.
    -- "lookup k l": Hier erfolgt die Suche nach "k" in der Liste "l".
    
    loesche :: Eq k => k -> WBuch k v -> WBuch k v
    loesche key (D l) = D [(k,v) | (k,v) <- l, k/=key]
    --Hier habe ich große Probleme den Ablauf zu verstehen.
    -- "key" ist der Wert, der gelöscht werden soll. Der Wert ist der Schlüsselwert der Liste "D"
    --Durch den Guard "|" wird überprüft, ob die Liste (k,v) gleich der Liste (k,v) <- l ist. "(k,v) <- l"
    -- soll dann wohl heißen, das (k,v) der Liste "l" entspricht.
    -- Wird der Wert dann durch "k/=key" gelöscht?
    -- Wieso muss hier nicht mit lookup überprüft werden, ob der Wert überhaupt existiert?
    -- Reicht dafür Eq aus? Wenn ja, wieso wurde dann bei der Funktion "finde" der Wert mit "lookup" gesucht.
    

    Und hier das zweite Modul "modulAdressbuch"

    module Adressbuch (
    	Name,
    	Adresse,
    	Adressbuch,
    	leeresAdressbuch,
    	einfuegen,
    	finde,
    	aktualisiere) where
    
    import qualified Woerterbuch as W
    -- Damit man mit den Funktionen aus dem anderen Modul arbeiten kann, wird es hier importiert und über "W"
    -- kann amn die Funktionen aufrufen
    
    type Name		= String
    type Adresse	= String
    newtype Adressbuch	= A (W.WBuch Name Adresse) deriving Show
    
    -- So ganz verstehe ich den Sinn von "type" und "newtype" noch nicht. Der Compiler kann doch hier gar nicht unterscheiden,
    -- ob der Name oder die Adresse gemeint sind, da dieser doch beide nur als "String" sieht.
    -- Und für Adressbuch gibt es ja nur einen Typen, hier müsste anstatt "newtype" doch "type" ausreichen.
    -- Das Adressbuch ist vom Typ "A" ( muss das A denn nun wegen dem newtype angegeben werden pder weil es sich um Tupel handelt?)
    -- Die Liste A enthält die Werte aus dem Modul Woerterbuch und der Name entspricht dem "k" und die Adresse
    -- entspricht dem "v" der Liste WBuch. ( Kann man hier nicht auch "D" angeben? ")
    -- Show wandelt dies für die Ausgabe wieder als String um.
    
    toWBuch (A d) = d
    fromWBuch d = A d
    
    -- Oben steht (A d ) in Klammern und unten nicht. Wieso?
    -- Leider verstehe ich nicht, wie und was hier genau gemacht wird.
    -- "d = A d" heißt das, dass "d" das Adressbuch A ist und der Wert "d" in die Liste 
    -- vom WBuch k v geschrieben wird?
    
    leeresAdressbuch :: Adressbuch
    leeresAdressbuch = fromWBuch W.leeresWBuch
    --da "fromWBuch" = A d ist, könnte man dann hier anstellen von "fromWBuch W...." einfach
    -- leeresAdressbuch = A d W.leeresWBuch schreiben?
    --
    
    einfuegen :: (Name, Adresse) -> Adressbuch -> Adressbuch
    einfuegen x = fromWBuch . W.einfuegen x . toWBuch
    -- x entspricht Name und Adresse und wird in der Funktion "W.einfuegen x" eingefügt.
    -- Reicht es hier denn nicht, W.einfuegen x aufzurufen? Wahrscheinlich nicht aber wieso denn nicht.
    
    finde :: Name -> Adressbuch -> Maybe Adresse
    finde n = W.finde n.toWBuch
    -- Name ist = n und Ergebnis soll ein Typ von Adressbuch sein."n.toWBuch" ist gleich n (A d) ?
    

    es ist doch so einiges recht verwirrend und ich hoffe, dass man hier etwas Licht ins dunkle bringen kann. Über Antworten würde ich mich sehr freuen!



  • Hallo Schmidto,

    da hast du dir aber etwas vorgenommen, Haskell als erste Programmiersprache zu erlernen: m.E. ist es nicht so einfach gleich funktional und rekursiv zu denken (da einem sequentielle Abläufe ersteinmal einfacher erscheinen).

    So wie ich deine Anmerkungen lese scheinst du noch generelle Verständnisschwierigkeiten mit den Datentypen und Parametern zu haben - dies ist bei funktionalen Sprachen auch etwas schwieriger zu lesen, da es eher in Kurzform und mathematischer aufgeschrieben wird.

    So nun aber zu einem Teil deiner Fragen:
    Mittels 'type' definierst du nur einen Aliasnamen für einen Datentypen, d.h. Name und Adresse sind intern auch nur "string" (so wie du richtig erkannt hast), aber für den Programmierer besser zu verstehen, als wenn überall nur "string" stehen würde.
    Und 'newtype' legt einen neuen Datentyp an, wobei im Beispiel 'D' einfach nur ein selbstgewählter Bezeichner steht (D steht wohl für Dictionary). Sicherlich hätte man auch überall im weiteren Code einfach nur [(k,v)] schreiben können (aber dann hätte man die gleichen Lese-Probleme wie ohne die Verwendung von Aliasnamen).

    Und zu den Parametern (Stichwort: Tupel und Currying):
    die 'einfuegen' Funktion erwartet nur 2 Parameter - x ist das hinzuzufügende Element und (D l) ist das Wörterbuch. Man hätte es jetzt auch folgendermaßen ausschreiben können:

    einfuegen :: (k, v) -> WBuch k  v -> WBuch k v
    einfuegen (k, v) (D [(lk, lv)]) = D ((k, v):[(lk, lv)])
    

    Aber wie du siehst, wäre die Schreibarbeit größer und der Code unübersichtlicher. Solange man nur als Ganzes auf einen Parameter zugreift, so braucht man eben nur eine Variable dafür. Nur wenn du auf die Inhalte zugreifen willst (per Pattern-Matching), z.B.

    einfuegen ([], v) (D l) = D (("leeres Element", v):l)
    

    benötigt man die explizite Schreibweise.
    Hätte man aber die Klammern bei dem 2. Parameter weggelassen, d.h. "einfuegen x D l", so wäre das dann als 3 Parameter interpretiert worden (und hätte einen Fehler gegeben, weil dies nicht zur Funktionsdeklaration gepasst hätte).

    Und dann noch zur Funktion "loesche". Mittels "[(k,v) | (k,v) <- l, k/=key]" erzeugt man eine neue Liste, mit der Bedingung, daß die bisherigen Elemente ungleich dem übergebenen Element sind (d.h. "[(k,v) | (k,v) <- l]" ist der Listenerzeugung-Operator und nur "k/=key" ist der Guard). Du kannst das lesen als "erzeuge eine neue Liste aller Tupel (k, v) aus der Liste l" - und ohne die Bedingung würde man einfach eine Kopie der Liste erstellen).
    Hätte man die Variable k nicht in der Bedingung gebraucht, so hätte man auch einfach "[x | x <- l]" schreiben können (auch hier wäre es wieder egal, was x genau ist).

    Und das "Eq k" soll (wohl) heißen, daß k ein Typ sein muß, der "vergleichbar" (equatable) ist, sonst kann man nicht die "lookup"-Funktion bzw. den gleich/ungleich-Operator benutzen.

    So ich hoffe ich konnte dir jetzt ersteinmal ein bißchen helfen. Du kannst aber gerne noch weitere Fragen im Detail hier stellen.

    P.S: Ich muß aber zugeben, daß ich Haskell selber nicht so gut kenne, sondern früher mit anderen FP programmiert habe (wie Miranda, Clean oder Gofer).



  • Th69 schrieb:

    da hast du dir aber etwas vorgenommen, Haskell als erste Programmiersprache zu erlernen: m.E. ist es nicht so einfach gleich funktional und rekursiv zu denken (da einem sequentielle Abläufe ersteinmal einfacher erscheinen).

    Es gibt da ja auch die Meinung, dass man funktionale Programmierung viel einfacher verstehen würde, wenn man vorher nicht imperativ "verseucht" ist. Es fasziniert mich daher etwas, hier Haskell als erste Programmiersprache sozusagen in freier Wildbahn beobachten zu können.

    Und das "Eq k" soll (wohl) heißen, daß k ein Typ sein muß, der "vergleichbar" (equatable) ist, sonst kann man nicht die "lookup"-Funktion bzw. den gleich/ungleich-Operator benutzen.

    Ja, der Begriff ist Typklasse. Das Eq k => heißt, dass der Typ k eine Instanz der Typklasse Eq sein muss.

    Eine Sache, die noch offen war: Es kam die Frage auf, was das (D l) in der Argumentliste bedeutet. Das ist Pattern Matching. Man könnte auch

    einfuegen x y = ...
    

    Ruft man dann

    einfuegen (3, "baz") (D [(1, "foo"), (2, "bar")])
    

    auf, ist x = (3, "baz") und y = (D [(1, "foo"), (2, "bar")]) . Durch Angabe von (D l) statt y gilt diese Definition erstens nur für Aufrufe, bei denen für das zweite Argument der Typkonstruktor D benutzt wurde (wäre relevant, wenn es mehr als diesen einen gäbe), zweitens wird die Liste gleich "ausgepackt". Mit

    einfuegen x (D l) = ...
    

    ist dann gleich l = [(1, "foo"), (2, "bar")]



  • Vielen Dank für die Antworten!
    Das muss ich nun erst mal verarbeiten. Weitere Fragen werden heute also nicht mehr kommen 😉

    Schönen Abend noch.



  • So ich bin das mal durchgegangen und habe natürlich noch ein paar Fragen.

    Was ich mich plötzlich Frage ist: Wozu überhaupt zwei Module? Das Modul Adressbuch macht doch das gleiche wie das Modul Woerterbuch.

    newtype WBuch k v = D [(k,v)] deriving Show
    

    Also WBuch ist ja der Name des Typs aber heißt der Typ dann nicht WBuch k v?
    Würde dann nicht newtype WBuch = D... ausreichen?

    leeresBuch :: Eq k=> WBuch k v
    leeresWBuch        = D []
    

    Bei dieser Funktion wird kein Parameter erwartet. Wenn sie aufgerufen wird, wird eine leere Liste erzeugt.
    Aber wenn doch eh kein Wert zur Übergabe erwartet wird, wieso muss der Wert dann zu der Klasse Eq angehören?

    einfuegen :: (k, v) -> WBuch k  v -> WBuch k v
    einfuegen x (D l) = D (x:l)
    

    Wenn ich für "D" auch [(k,v)] schreiben könnte, würde die Funktion dann so lauten:

    einfuegen x ([(k,v)] l) = [(k,v)] (x:l)
    

    oder habe ich das zu wörtlich genommen?

    finde :: Eq k => k -> WBuch k v -> Maybe v
    finde k (D l)     = lookup k l
    

    Also wenn lookup ein Nothing ausgibt soll stattdessen Maybe v ausgegeben werden.
    Das passiert aber doch nur, wenn er die entsprechende Adresse in der Liste nicht findet. Würde er dann einfach einen willkürlichen Wert aus der Liste ausgeben? Ich bin mir hier nicht so wirklich im klaren, was für einen Wert Maybe v haben kann/soll.

    loesche :: Eq k => k -> WBuch k v -> WBuch k v
    loesche key (D l) = D [(k,v) | (k,v) <- l, k/=key]
    

    Wenn ich eine neue Liste erzeuge unter der Bedingung, dass das bisherige Element ungleich dem übergebenen Element ist, woher weiß die Funktion dann, welchen Wert ich löschen soll wenn doch das Element gar nicht in der Liste existiert?
    Ich übergebe der Funktion den Wert "Schmidt" also steht in key=Schmidt.
    Also soll der Eintrag Schmidt gelöscht werden. In der Funktion steht aber doch nur, das Schmidt ungleich dem Wert "k" sein soll und dann wird eine neue Liste l erstellt. Nur hat "l" doch genau den gleichen Inhalt wie vorher auch.



  • Ui, da hast du wirklich noch einige Verständnisschwierigkeiten.

    0. Ich denke die beiden Module wurden einfach gewählt, damit man sieht wie diese in Haskell benutzt werden können, so daß ein "Datenaustausch" zwischen Wörterbuch und Adressbuch gezeigt werden kann

    1. die Variablen k und v müssen einfach angegeben werden, damit sie auf der rechten Seite benutzt werden können (sonst Compilerfehler)

    2. hierauf kann ich dir keine eindeutige Antwort geben, aber du kannst ja mal ausprobieren was passiert, wenn du das "Eq k" entfernst.

    3. Nicht für D kann man [(k,v)] schreiben, sondern für l (hast du mein Beispiel dazu nicht richtig gelesen?)

    4. Maybe v kannst du dir wie einen Typen vorstellen, der entweder v oder aber ein "Nothing" bzw. "NIL" (not in list 😉 zurückgibt - in anderen Sprachen benutzt man z.B. "optional" oder "nullable" o.ä. dafür).

    5. Es wird eben eine neue Liste erstellt, mit der Bedingung, daß nur die Werte kopiert werden, welche ungleich dem übergebenen key sind (und somit eine Liste, aus der alle key-Elemente gelöscht wurden) - aber auch dies hatte ich schon geschrieben 😉

    Vllt. solltest du auch nicht gleich diesen kompletten Code benutzen, sondern sukzessive die einzelnen Funktionen erstellen und entsprechend praktisch anwenden.



  • Schmidto schrieb:

    leeresBuch :: Eq k=> WBuch k v
    leeresWBuch        = D []
    

    Bei dieser Funktion wird kein Parameter erwartet. Wenn sie aufgerufen wird, wird eine leere Liste erzeugt.
    Aber wenn doch eh kein Wert zur Übergabe erwartet wird, wieso muss der Wert dann zu der Klasse Eq angehören?

    Für diese Funktion wird das eigentlich nicht benötigt. Aber wenn du es weglässt, kann man damit WBuch-Werte mit nicht vergleichbaren Schlüsseln erzeugen, bei denen dann kein lookup möglich ist.



  • Danke für die Antworten.
    Ich bin schon dabei jede Funktion einzelnd zu testen und aber natürlich auch zu verstehen..

    @ TH69

    gelesen habe ich deinen Beitrag aber anscheind habe ich das ein oder andere einfach nur falsch interpretiert.



  • Bashar schrieb:

    Es gibt da ja auch die Meinung, dass man funktionale Programmierung viel einfacher verstehen würde, wenn man vorher nicht imperativ "verseucht" ist.

    ist das in einem Experiment von signifikantem Umfang ausprobiert worden ?

    das würde u.a. implizieren, daß man die kategorientheoretischen Monaden viel einfacher verstehen würde ohne Vorkenntnisse über Imperatives wie print und printf.



  • buchstaben schrieb:

    Bashar schrieb:

    Es gibt da ja auch die Meinung, dass man funktionale Programmierung viel einfacher verstehen würde, wenn man vorher nicht imperativ "verseucht" ist.

    ist das in einem Experiment von signifikantem Umfang ausprobiert worden ?

    Keine Ahnung, vermutlich nicht. Mir sind überhaupt keine Experimente zum Thema Lernen und Verstehen von Programmiersprachen bekannt, nur Meinungen.



  • Bashar schrieb:

    Für diese Funktion wird das eigentlich nicht benötigt. Aber wenn du es weglässt, kann man damit WBuch-Werte mit nicht vergleichbaren Schlüsseln erzeugen, bei denen dann kein lookup möglich ist.

    Wie kann ich denn mit der Funktion nicht vergleichbare Schlüssel erzeugen, wenn ich am Ende doch nur eine leere Liste D [] bekomme?

    @TH69

    Und 'newtype' legt einen neuen Datentyp an, wobei im Beispiel 'D' einfach nur ein selbstgewählter Bezeichner steht (D steht wohl für Dictionary). Sicherlich hätte man auch überall im weiteren Code einfach nur [(k,v)] schreiben können (aber dann hätte man die gleichen Lese-Probleme wie ohne die Verwendung von Aliasnamen).

    das hatte ich so verstanden, dass ich einfach das "D" überall mit [(k,v)] ersetzen könnte 😉



  • Aber nicht für das 'D' alleine, sondern für den gesamten Datentyp (D l).



  • ok verstanden 😉

    4. Maybe v kannst du dir wie einen Typen vorstellen, der entweder v oder aber ein "Nothing" bzw. "NIL" (not in list 😉 zurückgibt - in anderen Sprachen benutzt man z.B. "optional" oder "nullable" o.ä. dafür).

    Also wnen Maybe ein Typ ist aber v den selben Typen hat wie k.. dann ergibt das maybe doch gar keinen Unterschied

    finde :: Eq k => k -> WBuch k v -> k
    

    wäre dann doch das gleiche.



  • Also mit den neuen Informationen, versuche ich mal nun folgende Funktion zu erklären:

    einfuegen :: (Name, Adresse) -> Adressbuch -> Adressbuch
    einfuegen x = fromWBuch . W.einfuegen x . toWBuch
    

    Es wird die Funktion einfuegen im Modul Woerterbuch aufgerufen.
    Diese Funktion erwartet als Eingabe folgende Typen:

    einfuegen :: (k, v) -> WBuch k  v -> WBuch k v
    einfuegen x (D l) = D (x:l)
    

    Name und Adresse sind also (a,b)
    Leider fällt es mir jetzt schon sehr schwer, den weiteren Ablauf zu erklären. In der Signatur steht,
    dass nun der Typ Adressbuch erwartet wird und dieser wird wohl mit fromWBuch übergeben.
    Aber die Funktion einfuegen im Woerterbuch benötigt doch den Typ WBuch also toWBuch.
    "W.einfuegen x . toWBuch" diese zwei Werte werden doch an die Funktion einfuegen aus dem Woerterbuch übergeben.
    Durch toWBuch wird auch der passende Typ übergeben.
    Aber wozu brauch ich denn das fromWBuch?
    Auch die Signatur aus der Funktion einfuegen im Adressbuch verstehe ich nicht so ganz.

    einfuegen :: (Name, Adresse) -> Adressbuch -> Adressbuch
    

    am Ende kommt doch der Typ WBuch raus und nicht Adressbuch...



  • Es wurde zwar schonmal gesagt, aber du verwechselst newtype mit type .

    In der Benutzung ist ein Typ mit newtype genau das gleiche wie einer mit data , stell dir also vor, anstatt newtype stünde überall data.



  • ist mir gar nicht bewusst das ich das tue.. 😞

    einfuegen :: (Name, Adresse) -> Adressbuch -> Adressbuch
    einfuegen x = fromWBuch . W.einfuegen x . toWBuch
    

    dieser Teil ist mir ja klar denke ich:

    W.einfuegen x . toWBuch
    

    da die Funktion im Wörternuch das x und halt den Typ WBuch benötigt.
    das fromWBuch steht ja VOR dem Funktionsaufruf.. durch den "." vor dem "W.einfuegen" wird dadurch der Rückgabetyp von der Funktion W.einfuegen also WBuch dann zu einem Adressbuch?



  • einfuegen :: (Name, Adresse) -> Adressbuch -> Adressbuch
    einfuegen x = fromWBuch . W.einfuegen x . toWBuch
    

    Erstmal die Signatur analysieren. Der -> Operator ist rechtsassoziativ, sie wird also als

    einfuegen :: (Name, Adresse) -> (Adressbuch -> Adressbuch)
    

    verstanden. Übersetzt: einfuegen ist eine Funktion, der man ein Paar (Name,Adresse) übergibt, und die eine Funktion, die ein Adressbuch auf ein Adressbuch abbildet, zurückgibt.

    In der Definition sieht man nun den .-Operator für die Komposition von Funktionen. Komposition ist die Hintereinanderausführung von Funktionen, (f . g) x bedeutet f (g x). einfuegen x ergibt also eine Funktion, die auf ihr Argument, ein Adressbuch, zuerst toWBuch anwendet (es kommt ein WBuch heraus), dann auf das Ergebnis die einfuegen-Funktion aus dem Woerterbuch-Modul anwendet (es kommt ein WBuch mit eingefügtem x heraus), auf das Ergebnis dann fromWBuch anwendet (es kommt ein Adressbuch heraus).

    Man kann die Signatur von einfuegen auch so verstehen, dass dort zwei Parameter, ein Paar (Name,Adresse) und ein Adressbuch, übergeben werden und ein Adressbuch herauskommt. Das Prinzip des Curryings besagt, dass man Funktionen mit mehreren Argumenten als Funktionen mit einem Argument, die eine weitere Funktion zurückgeben, auffassen kann. Das wäre dann die obige Interpretation. Man hätte einfuegen aber auch in der nicht gecurryten Form schreiben können:

    einfuegen :: (Name, Adresse) -> Adressbuch -> Adressbuch
    einfuegen x a = fromWBuch (W.einfuegen x (toWBuch a))
    


  • Bashar schrieb:

    Th69 schrieb:

    da hast du dir aber etwas vorgenommen, Haskell als erste Programmiersprache zu erlernen: m.E. ist es nicht so einfach gleich funktional und rekursiv zu denken (da einem sequentielle Abläufe ersteinmal einfacher erscheinen).

    Es gibt da ja auch die Meinung, dass man funktionale Programmierung viel einfacher verstehen würde, wenn man vorher nicht imperativ "verseucht" ist.

    Gibts diese Meinung auch außerhalb dieses Forums? Oder ist diese Meinung einfach nur eine Ausrede?



  • Da der Großteil der (programmierenden) Weltbevölkerung nicht in diesem Forum ist, gehe ich davon aus, dass es auch da Menschen gibt, die diese Meinung haben.
    Man könnte ja mal eine richtige Studie mit zufallseingeteilten Gruppen usw. machen. 😉
    Aber wofür sollte es eine Ausrede sein?

    Ich fand's auch interessant, dass Schmidto sich Haskell als erste Sprache ausgesucht hat, aber warum auch nicht? 🙂
    Gerade bei Mathematikern könnte ich mir vorstellen, dass es einige von ihnen intuitiv schneller funktional als imperativ Programmieren können.



  • Dobi schrieb:

    Aber wofür sollte es eine Ausrede sein?

    Dafür, dass Haskell einfach nicht intuitiv zu erlernen ist. Jetzt versuchen die Haskell Fans sich halt darauf raus zu reden, dass man vorher zuviel imperativ programmiert hat.


Anmelden zum Antworten