Funktionale Programmierung mit Haskell



  • 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.



  • u_ser-l schrieb:

    so auf den ersten Blick scheint der xmonad-code aber geradezu vor "do" zu wimmeln

    Genau das ist der Punkt. 🙂 Es geht um die saubere Trennung des funktionalen Teils von dem Teil mit den Seiteneffekten. Der funktionale Code steht jetzt natürlich nicht wirklich vor dem 'do', sondern wird in den Monaden verwendet, so wie du es hier schon sehr treffend beschreibst.
    Im übrigen lässt sich diese saubere Trennung auch schon an den Datentypen der Funktionen ablesen. Man muss also nichtmal in die einzelnen Funktionen hinein schauen, um zu wissen, welche Seiteneffekte haben könnte und welche nicht.

    u_ser-l schrieb:

    und hinter jedem davon versteckt sich ein "Nest" imperativer Anweisungsfolgen.

    Naja, Nest klingt nach echt viel, aber in der Regel hast du hinter jedem 'do' weniger als 10 imperative Anweisungen. Also etwa in dem Bereich von 7+-2 Chunks 🙂

    u_ser-l schrieb:

    Das, was man in der reinen funktionalen Programmierung zur Vordertür herausstoßen wollte, kommt durch den Lieferanteneingang "Monade" wieder herein.

    Es ist ja nicht so, dass man Seiteneffekte aus Haskell verbannen wollte. Denn man wollte ja auch schon immer eine nützliche Sprache haben, was natürlich nur mit Seiteneffekten geht. Aber das Ziel ist es, Seiteneffekte erkennbar, handhabbar, ja beherrschbar zu machen. Und das ist, wie ich finde, durch Monaden wundbar gelöst.

    Auf der anderen Seite ist es ja z.B. auch in C++ oder in C möglich, eine rein funktionale Funktion zu schreiben. sin(x), oder cos(x) sind schöne Beispiele dafür. Diese Funktionen sind tatsächlich seiteneffektfrei. Man wird aber auch nicht dazu gezwungen, nicht mal dazu, Seiteneffekte erkennbar zu machen. Und man kann dies auch nicht am Datentyp der Funktion erkennen, was dazu führt, dass man nicht weiß, wo Seiteneffekte auftreten können. Und genau hier liegt sicher auch eine Fehlerquelle.

    u_ser-l schrieb:

    Trotzdem, zugegeben, xmonad ist ein eindrucksvoller proof-of-concept in funktionaler Programmierung.

    Absolut, ich bin auch immer wieder auf's neue von xmonad fasziniert. Ich nutze bald 10Jahre (seitdem es larswm gibt) diese tailing wm's. Hab da jetzt doch schon ein paar gesehen, und xmonad übertrifft alles 🙂 Der rockt einfach 🙂



  • minhen schrieb:

    Wenn du das unter "Rekursion erklären" verstehst, nur weil man eine andere Meinung als du hast ...

    Nein das tue ich nicht. Ich glaube nur, dass viele Leute, die Rekursion nicht verstehen, die Dinge so erklärt bekommen haben. Ich weiß nicht, wie du Rekursion den Leuten näher bringst, darum kann ich mir kein Urteil darüber erlauben. An dem Punkt frage ich mich außerdem, wie es dazu kommt, dass ich immer wieder Leute treffen, die meinen, dass man Rekursion verwendet, damit das Programm schneller läuft. 😕 Da kann dann doch irgendwas nicht richtig erklärt werden.

    minhen schrieb:

    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 ...

    Das ist natürlich nicht einfach und muss gelernt werden. Die Frage ist halt, wenn du das formulieren kannst, welche der beiden Varianten direkter deine Überlegungen in Quelltext gießen. Dass das erst gelernt werden muss, steht außer Frage. Ich behaupte nur, dass sich das lohnt, eben weil unsere Denkweise nicht prozedural ist. Und obwohl wir es vielleicht gewohnt sind, gewisse Lösungen prozedural zu formulieren.

    @frosch03
    Sicherlich leistet Microsoft so einiges in der Forschung. Wobei ich dich wieder nach deinen Quellen frage, für deine Behauptung.

    Der GHC ist unter der BSD-Lizenz und das Copyright liegt bei "The University Court of the University of Glasgow". Willst du performanten Code erzeugen, kommst du am GHC nicht vorbei. Aber wenn man das mit den im Moment eingesetzten Script-Sprachen vergleicht, so gibt es da noch weitere Haskell-Compiler, die es an Performance locker mit den Script-Sprachen aufnehmen können. Ich schreibe das nur nochmal, weil ich finde, dass das "Microsoft-Argument" nun wirklich kein Argument gegen Haskell und den GHC ist.



  • An dem Punkt frage ich mich außerdem, wie es dazu kommt, dass ich immer wieder Leute treffen, die meinen, dass man Rekursion verwendet, damit das Programm schneller läuft. 😕 Da kann dann doch irgendwas nicht richtig erklärt werden.

    Im einfachsten Fall, weil die Objekte auf dem Stack gepackt werden. Im Bereich der Funktionalen Programmierung hat man bei Rekursion aber noch ganz andere Optimierungsmoeglichkeiten: z.B. tail transfer (auch tail recursion oder tail call optimisation genannt).



  • knivil schrieb:

    Im Bereich der Funktionalen Programmierung hat man bei Rekursion aber noch ganz andere Optimierungsmoeglichkeiten: z.B. tail transfer (auch tail recursion oder tail call optimisation genannt).

    höhere programmiersprachen machen aus rekursionen intern oft schleifen. der programmierer merkt natürlich nix davon. für 'nen realen computer, der bits und bytes durch die gegend scheucht, sind rekursionen mühsamer als schleifen.
    🙂



  • höhere programmiersprachen machen aus rekursionen intern oft schleifen.

    Intern kennt der Computer keine Schleifen nur Spruenge. Jedoch mag tail code optimisation auf Assemblerebene wie Assembler von Schleifen aussehen, Aber Schleifen und Rekursion sind trotzdem verschiedene Konzepte. Iteration wird in Scheme trotzdem durch eine rekursive Notation ausgedrueckt.



  • knivil schrieb:

    Intern kennt der Computer keine Schleifen nur Spruenge.

    ich bitte dich. es gibt einige cpus instructions, die bei sprüngen automatisch irgendwelche register hoch/runterzählen oder sogar 'loop' heissen.

    knivil schrieb:

    Auch wird mein C++ Kompiler nie aus einer Rekursion eine Schleife machen.

    sag niemals nie. wenn er's macht, merkst du jedenfalls nichts davon.
    🙂


Anmelden zum Antworten