Funktionale Programmierung mit Haskell
-
frosch03 schrieb:
Natürlich ist Haskell standardisiert worden, allerdings ist das 11 Jahre her.
Nur der Vollständigkeit halber: Der Haskell 98 Report ist zwar von Ende 1998, aber die aktuelle (revidierte) Fassung ist von Dezember 2002, also nur etwas über 6 Jahre alt: http://www.haskell.org/onlinereport/
-
frosch03 schrieb:
Auch Mathematik ist für viele Menschen ein Buch mit sieben Siegeln und doch währe eine Welt ohne Mathe nicht denkbar .
Rechtschreibung auch
frosch03 schrieb:
Zu guter letzt wollte ich noch sagen, dass ich diese ganze Urzeit-/Jagd-/Evolutions-/Denk-Diskusion für ziemlich sinnfrei halte.
Ganz im Gegenteil. Um menschengerechte Mnemonik entwickeln zu können, muß man menschliches Denken verstehen, und dazu muß man verstehen, wie menschliches Denken zustande kommt und sich entwickelt hat.
Mnemonik zählt.
Die Auffassung, der Mensch sei eine Art Roboter mit eingebautem Computer, führt nur zu immer weiteren Syntax-Monstern und unbedienbaren Mensch/Maschine-Interfaces.
-
Das hat doch wenig bis gar nichts mit Mnemonik zu tun. Es ist doch nicht das Problem, dass man sich die Syntax einer Programmiersprache nicht merken könnte. Ich vermute, was Rekursion so schwer macht, ist einfach der Umstand, dass es ein eigenständiges, nicht triviales Konzept ist. Während man bei der prozeduralen Programmierung im Grunde klar der Reihe nach stehen hat, was wann wo wie passiert, ist das bei Rekursion nicht der Fall. Im Gegensatz zu vielen anderen Dingen kann man das, was bei der Rekursion nicht explizit dort steht, auch nicht einfach ignorieren. Bei einem Funktionsaufruf brauch ich mir keinen Kopf um den Stack oder sonstige Interna machen. Und selbst bei der Unifikation zweier Variabeln kann mir das Backtracking erst einmal egal sein. Aber bei der Rekursion ist das, was nicht dort steht, der eigentliche Kern, der springende Punkt, das Thema der ganzen Angelegenheit. Es scheint einfach einfacher zu sein, exakt das hinzutippen, was man sich denkt, wenn man das Problem durchgeht: Erst mach ich das, dann das, dann das. Die zusätzliche Abstraktionsstufe, dass sich der Abflauf hier und dort wiederholt und so und so zusammenfassen lässt und damit diesen eleganten, rekursiven Algorithmus ergibt, die scheint das Problem zu sein. Es ist ja nicht so, dass Anfänger einen gegebenen rekursiven Algorithmus nicht verstehen oder nachvollziehen könnten. Das Problem, das sie meiner Erfahrung nach haben, ist schlicht und ergreifend zu einer Aufgabenstellung selbstständig eine rekursive Lösung zu finden. Das Nachvollziehen einer gegebenen Lösung ist dagegen meistens eher kein Problem.
Das mit Abstand größte Problem für Anfänger ist aber nachwievor ein Problem einfach nur streng und exakt durchzudenken. Das ist das größte Problem und betrifft sämtliche Programmiersprachen. Bei Rekursion, welche für deklarative Sprachen grundlegend ist, kommt ein zusätzlicher Abstraktionsschritt dazu. Der stellt für sich alleine schon eine Herausforderung dar. Und wenn man als Anfänger noch mit dem Problem Nummer eins hadert, wird's durch Rekursion garantiert nicht besser. Wenn ich für jedes Programm eines Anfängers einen Euro bekommen hätte, bei dem sich die Rekursion in die Unendlichkeit verabschiedet bis in den meisten Fällen der Stack überläuft. Das wär was gewesen
Aber mit Natürlichkeit und Unnatürlichkeit und wie der Mensch selbst im Hirnkastal denkt, hat das wenig zu tun. Menschen könnten ohne Weiteres "rekursiv denken" und der implizite Abstraktionsschritt im Formalismus würde den Anfängern trotzdem schwer fallen. Das wäre wie mit Sprache und Grammatik. Wir alle haben die deutsche Grammatik intus und können grammatikalische Sätze produzieren, erkennen und verstehen und wissen, wenn ein Satz irgendwie "kein richtiges Deutsch" ist. Und das irgendwie ist der zentrale Punkt. Wehe man muss die Regeln, die man zweifelsohne beherrscht, ausbuchstabieren, aufschreiben oder auch nur bewusst anwenden ...
-
Ohne mich jetzt allzusehr in diesen Thread hineinwerfen zu wollen: Vergesst nicht, dass der persönliche Hintergrund den Zugang zu verschiedensten Konzepten und Sprachen stark beeinflusst.
Ich habe mal ein paar viertsemestrigen Mathematikern, die vorher noch nie programmiert hatten, die Grundlagen von Haskell gezeigt. Die hatten natürlich keinerlei Schwierigkeiten mit Rekursion (Klar, kommt ja in mathematischen Definitionen auch ständig vor.) und diversen Eigenheiten der funktionalen Programmierung.
-
minhen schrieb:
Das hat doch wenig bis gar nichts mit Mnemonik zu tun.
ich finde schon - ein funktionaler Ausdruck wie
t := a(b(c, x1), x2(d, y(3)), e)
erfordert vom Benutzer, mehr Symbole gleichzeitig im Kurzzeitgedächtnis zu halten als
der sequentiell notierteb_ := b(c,x1) y_ := y(3) x_ := x2(d,y_) res := a(b_,x_,e)
vielleicht nicht das beste Beispiel, aber das Prinzip wird klar.
Die Kurzzeitgedächtnis-Leistung des Menschen ist eine kostbare Resource, da sie sehr begrenzt ist (nur wenige Bytes), und ein guter Formalismus sollte sparsam damit umgehen - das meine ich auch mit
"Mnemonik".
-
u_ser-l schrieb:
der sequentiell notierte
b_ := b(c,x1) y_ := y(3) x_ := x2(d,y_) res := a(b_,x_,e)
vielleicht nicht das beste Beispiel, aber das Prinzip wird klar.
-- Haskell let b_ = b c x1 y_ = y 3 x_ = x2 d y_ in a b_ x_ e
-
ich meine mit "sequentiell" schon, daß die Funktionen y, x, a von einer Art sein, daß sie nur hintereinander ausgeführt werden können sollen, aber zugegeben, das Beispiel ist nicht so gut
-
Wenn du das meintest, warum schreibst du dann was von der Zahl der Symbole, mit denen das Kurzzeitgedächtnis gleichzeitig hantieren muss? Das sind vollkommen separate Probleme. Das eine löst man durch Einführung von Zwischenvariablen, was in funktionalen Sprachen üblicherweise durch das let-Konstrukt (in Haskell auch nachgestelltes where) geschieht, das andere in Sprachen mit eager evaluation (wie ML oder Scheme) genauso wie in imperativen Sprachen und in Haskell durch Monaden.
-
naja, so ganz unabhängig ist das ja doch nicht. Ähnlich wie in Forth, wo man bei der Programmierung ständig einen Teil des Stacks in Gedanken halten muß. Wie dem auch sei, es ändert aber nichts daran, daß Programme zur Lösung von real-world-Problemen oft gewisse Teilaspekte der real world simulieren müssen, und dabei spielen Zustände und Zustandsübergänge eine wesentliche Rolle, wogegen die reine FP 'zeitlos' ist - da sehe ich einen Ziel-Konflikt.
Daß FP zur Beschreibung bestimmter Probleme, zB massiv parallelisierbarer Algorithmen und rekursiver Datenstrukturen, gut geeignet ist, bezweifle ich gar nicht. Für jeden Zweck den optimalen Formalismus.
-
u_ser-l schrieb:
Für jeden Zweck den optimalen Formalismus.
Das ist sowieso das einzig Sinnvolle.
-
u_ser-l schrieb:
Ganz im Gegenteil. Um menschengerechte Mnemonik entwickeln zu können, muß man menschliches Denken verstehen, und dazu muß man verstehen, wie menschliches Denken zustande kommt und sich entwickelt hat.
Kein Plan, wo du jetzt von der Spekulation über das sequentielle/parallel Jagtverhalten von Urmenschen auf Mnemoniks kommst. Und selbst wenn du da irgendwie einen Link herstellen kannst, was hat das mit funProg zu tun???
u_ser-l schrieb:
führt nur zu immer weiteren Syntax-Monstern und unbedienbaren Mensch/Maschine-Interfaces.
Kannst du mir kurz ein funProg-Syntax-Monster nennen, bzw. kurz andeuten was genau du damit meinst?
Übrigens möchte ich mich davor bewahren, die Leistung meines Kurzzeitgedächtnisses in Bytes auszudrücken :), geschweigedenn darüber zu mutmaßen, wie groß es denn sei. Auch verstehe ich wirklich nicht, was die ganze Thematik überhaupt mit dem Kurzzeitgedächtniss zu tun hat.
Und dann muss ich dir auch sagen, dass ich die schreibweise deines Beispieles wirklich nicht einfach zu lesen fand. Keine Ahnung wie das den anderen hier ging, aber bei mir hats 'n Moment gedauert :). (Soviel zum Thema, eingänigere Schreibweise :))
u_ser-l schrieb:
Programme zur Lösung von real-world-Problemen oft gewisse Teilaspekte der real world simulieren müssen, und dabei spielen Zustände und Zustandsübergänge eine wesentliche Rolle, wogegen die reine FP 'zeitlos' ist - da sehe ich einen Ziel-Konflikt.
Sowas wie ein Fenstermanager, der sich die Zustände von Fenster merken muss bzw. diese ändert, auf Userinteraktion reagiert, usw.?
-
frosch03 schrieb:
Übrigens möchte ich mich davor bewahren, die Leistung meines Kurzzeitgedächtnisses in Bytes auszudrücken :), geschweigedenn darüber zu mutmaßen, wie groß es denn sei. Auch verstehe ich wirklich nicht, was die ganze Thematik überhaupt mit dem Kurzzeitgedächtniss zu tun hat.
Sofern du ein normaler Mensch ist sollte dein Kurzzeitgedächtnis 7 +/- 2 Chunks Kapazität haben.Der Unterschied zwischen Chunks und Bytes ist dabei in etwa ... sagen wir einfach so, ein Chunk ist eher ein Zeiger
-
-
Na gut, die 7+-2 Story kenn ich, und mit Chunks kann ich mich auch echt anfreunden Aber bitte keine Bytes Sonst werden wir noch zu den Syntaxmonstern so wie u_ser-l sie schon angedeutet hat Und damit hatter auf jeden Fall recht, sowas sind wir nicht ...
-
frosch03 schrieb:
Kein Plan, wo du jetzt von der Spekulation über das sequentielle/parallel Jagtverhalten von Urmenschen auf Mnemoniks kommst.
die Frage war, ob FP dem natürlichen menschlichen Denken entspricht. Da schadet es doch nicht, sich zu überlegen, wofür unser Denkapparat evolutionär eigentlich gedacht ist, und mit welchen Paradigmen und Formalismen man dem am ehesten gerecht wird.
OOP z.B. kommt dem menschlichen Denken sehr entgegen - die Kapselung schont das Kurzzeitgedächtnis, die Interfaces zwingen den Programmierer strategisch zu denken, außerdem ist
die für ein OOP-System notwendige Minimalsyntax "Objekt Nachricht" eine gute Metapher für natürliche Kommunikation zwischen Menschen.frosch03 schrieb:
Sowas wie ein Fenstermanager, der sich die Zustände von Fenster merken muss bzw. diese ändert, auf Userinteraktion reagiert, usw.?
Ich weiß, es gibt einen window manager, der in Haskell implementiert ist, und einen in Scheme.
-
u_ser-l schrieb:
Ich weiß, es gibt einen window manager, der in Haskell implementiert ist, und einen in Scheme.
Aber ist das nicht die Sorte von Problemen, die nach deiner Argumentation nur sehr schwierig in funProgs abzubilden sind?
-
kann ich so nicht sagen, ich habe noch keinen wm programmiert. Möglich ist so etwas in nahezu jeder Prog.sprache, die bindings zu X libraries zur Verfügung stellt.
-
tatsächlich, xmonad besteht aus ziemlich wenig codezeilen. Aber sehe ich das richtig, daß man einen kompletten Haskell-compiler installieren muß, um xmonad zu konfigurieren ?
-
u_ser-l schrieb:
Möglich ist so etwas in nahezu jeder Prog.sprache, die bindings zu X libraries zur Verfügung stellt.
Dem hab ich nichts hinzuzufügen.
Aber es wahren auch deine Worte, dass:u_ser-l schrieb:
eine Nachbildung sequentiellen Verhaltens durch kategorientheoretische Tricks
und
u_ser-l schrieb:
Probleme aus der realen Welt lassen sich oft am einfachsten durch Zustände, Übergänge und sequentielle Abläufe modellieren, also genau das, was mit FP kompliziert ist
Daher das Beispiel mit dem Windowmanager, der ja nichts anderes als eine Zustandsmaschine ist (man könnte auch Mealy-Automat dazu sagen). Und genau diese Zustandsmaschine ist in Haskell in weniger Zeilen Code implementiert, als die vergleichbaren prozedual/imperativen Lösungen. Da ich den Source von xmonad im Detail kenne, so wie auch den Source von wmii sowie larswm, kann ich sagen, dass xmonad nicht nur kürzer, sondern auch viel sauberer (schöner) implementiert ist. Im übrigen leistet xmonad deutlich mehr als wmii oder larswm.
Verstehst du was ich meine? xmonad ist das Beispiel dafür, dass das hantieren mit Zuständen in funProg. nicht das üble Problem ist, dem man nur unter höchstem Aufwand (die von dir genannten kategorientheoretischen Tricks) begegnen kann. In Wirklichkeit ist xmonad sogar dazu geeignet um Anfängern der funProg. diese näher zu bringen. (siehe "A Taste of Haskell": http://conferences.oreillynet.com/pub/w/58/tutorials.html)
Und dass es auch in anderen Sprachen möglich ist wm's zu schreiben, dagegen will ich garnicht argumentieren.
-
so auf den ersten Blick scheint der xmonad-code aber geradezu vor "do" zu wimmeln - und hinter jedem davon versteckt sich ein "Nest" imperativer Anweisungsfolgen. Das, was man in der reinen funktionalen Programmierung zur Vordertür herausstoßen wollte, kommt durch den Lieferanteneingang "Monade" wieder herein.
Trotzdem, zugegeben, xmonad ist ein eindrucksvoller proof-of-concept in funktionaler Programmierung.