NeX hat geschrieben:so noch eine frage die sich gerade wieder egeben hat....
folgende Situation 30/10 + foo(....)
foo :: [Int] -> Int
wie sieht der nächste auswertungsschritt aus?
(i) 3 + foo(...)
hier wäre es meine auffassung von leftmost outermost....
er muss den ausdruck 30/10 ja auch auswerten um + rechnen zukönnen...
(ii) 30/10 + (40/10 +foo(....))
hier würde ich sagen das er weiss das 30/10 eine Int Zahl ist und bei foo
weiss er das noch nicht....
somit weiss ich wieder nicht was sache ist

So, hier mal etwas zu genau diesem Thema, was Herr Giesl nochmal beleuchtet hat. Sei der folgende Code gegeben:
- Code: Alles auswählen
length [] = 0
length (_:xs) = 1 + length xs
head (x:_) = x
facs 0 = [1]
facs (n+1) = (n+1) * (head facs n) : facs n
isEmpty1 [] = True
isEmpty1 (_:_) = False
isEmpty2 xs = length xs == 0
(Das ist aus der Übung 11 im WS05/06)
Die Frage ist jetzt, wie isEmpty2 ausgewertet werden soll für einen
Aufruf isEmpty2 facs 2 (ein paar Schritte ausgelassen, um schneller zum
interessanten Teil zu kommen):
- Code: Alles auswählen
isEmpty2 facs 2
-> length 2 * (head facs 1) : facs 1
-> 1 + length facs 1
-> 1 + length 1 * (head facs 0) : facs 0
-> 1 + 1 + length facs 0
(a) -> 2 + length facs 0
(b) -> 1 + 1 + length 1:[]
Dazu nun die Antwort von Prof. Giesl:
Prof. Giesl hat geschrieben:(b) ist richtig und zwar aus folgendem Grund:
Da steht am Anfang 1 + (1 + length facs 0), mit dieser Klammerung.
Dass + assoziativ ist, wei Haskell nicht. Da + nur auswerten kann,
wenn beide Argumente bereits voll ausgewertete Zahlen sind, kann
keines der beiden + selbst ausgewertet werden. Stattdessen muss
man bei der Auswertung von length facs 0 weitermachen.
Dazu nochmal ein Kommentar von mir: Ich bin mir nicht sicher, dass das unbedingt so sein muss, sondern glaube, dass das ein Implementationsdetail ist, denn:
1 + 1 + 1 + foo könnte auch als (((1 + 1) + 1) + foo) geklammert sein (wenn der Parser entsprechend arbeitet und immer den Operator ganz rechts zuerst betrachtet). Dann ist aber Outermost bar + foo [mit bar == ((1+1)+1)], das kann nicht ausgewertet werden, weil beide Teilausdrücke nicht evaluiert worden sind. Der, der nun leftmost ist, ist bar, d.h. das führt zu 3 + foo. Wobei das rein hypothetisch ist, im Allgemeinen dürfte der Parser immer von links nach rechts gehen.