www.jammni.de

Logo - Kleiner Drache
Login
Username:

Passwort:

Daten merken
Auto-Login
Registrieren
 
Online
niemand
 
Forumsuche
Suche nach:

Logo - DracheHaskell-Forum

constructor

Gepostet:
19.06.2010 17:38

anonyme funktionen  
Hallo folgendes beispiel:

mnr=[0,1,2,3,4,5,6]

t2 = (\x -> \y -> (x (y x), x, y))

t3 = (\(x,_,_)->x) (t2(\x->x+1)(\x->mnr!!6))

hier sind n haufen anonymer funktionen. Und ich möchte den wert von t3 herausfinden.

Also erstens.
Eine anonyme fkt ist ja nichts anderes als eine Funktion quasi "inline" geschrieben die keinen Namen hat. richtig?
wenn ich mir t3 anschaue. wiegehe ich hier vor?
also ich fange von ganz hinten an (\x -> mnr!!6) ist eine anonyme funktion die jamit x nichts macht oder? diese funktion liefert mir nur den wert 6 zurück.
dann das nächste: (\x -> x+1) eine funktion die ihr eigenes argument um 1 inkrementiert. aber was is das argument x welchen wert hat das ? wo wird das aufgerufen?
letztendlich rufe ich t2 mit den zwei argumenten (\x->x+1)(\x->mnr!!6) auf, was legitim ist weil t2 als erstes und zweites argument zwei funktionen erwartet. Ist es hier egal wie diese funktionen ausschauen? und t2 liefert ja ein dreiertupel wo wird das dann weiter verwendet? ? ? könnte mir jemand mal das durchspielen wie haskell hier auf letztendliche ergebnis kommt?

lg

Zum Seitenanfang    
 
Siracusa

Gepostet:
20.06.2010 02:28

   
Hallo,

> Eine anonyme fkt ist ja nichts anderes als eine Funktion quasi "inline" geschrieben die keinen Namen hat. richtig?
Richtig.

> (\x -> mnr!!6) ist eine anonyme funktion die jamit x nichts macht oder?
Genau, egal welchen Wert x bekommt liefert die immer 6.

> (\x -> x+1) eine funktion die ihr eigenes argument um 1 inkrementiert. aber was is das argument x welchen wert hat das ? wo wird das aufgerufen?
Ist erstmal egal welchen Wert das hat, wichtig nur, die Funktion addiert nur 1 drauf.

> letztendlich rufe ich t2 mit den zwei argumenten (\x->x+1)(\x->mnr!!6) auf, was legitim ist weil t2 als erstes und zweites argument zwei funktionen erwartet. Ist es hier egal wie diese funktionen ausschauen?
Prinzipell ist es egal, solange die Funktionen auch vom Typ her zu den erwarteten Funktionen passen

> und t2 liefert ja ein dreiertupel wo wird das dann weiter verwendet?
t3 hat ja vorn nochmal eine Funktion, die aus einem Dreiertupel nur den ersten Wert zurückgibt, genau da wird das benutzt.

> könnte mir jemand mal das durchspielen wie haskell hier auf letztendliche ergebnis kommt?
Also, gegeben sind
mnr = [0,1,2,3,4,5,6]
t2 x y = (x (y x), x, y)
t3 = (\(x,_,_)->x) (t2 (\x->x+1) (\x->mnr!!6))

t3 hinten vereinfacht ergibt
t3 = (\(x,_,_)->x) (t2 (\x->x+1) (\x->6))

Jetzt den Teilausdruck mit t2 auswerten
t2 (\x->x+1) (\x->6)
= ((\x->x+1) ( (\x->6) (\x->x+1) ), \x->x+1, \x->6)

Das sieht vorn verwirrend aus, (y x) ist aber lediglich 6, denn egal welchen Wert y übergeben bekommt, liefert es 6 zurück. Also ist (x (y x)) gleich x angewendet auf 6, was 7 ergibt. Ergibt soweit also:
= (7, \x->x+1, \x->6)

Wieder eingestezt in die ursprüngliche Gleichung
t3 = (\(x,_,_)->x) (7, \x->x+1, \x->6)

liefert schlicht den ersten Wert des Tupels, nämlich 7, was dann auch das Endergebnis ist.


Viele Grüße,

Siracusa
Zum Seitenanfang    
 
constructor

Gepostet:
20.06.2010 11:23

   
Hallo, vielen, vielen Dank.
Mann, ist das verwirrend :-)

> Das sieht vorn verwirrend aus, (y x) ist aber lediglich 6, denn egal welchen Wert y übergeben bekommt, liefert es 6 zurück. Also ist (x (y x)) gleich x angewendet auf 6, was 7 ergibt. Ergibt soweit also:
da reden wir ja vom teil: ( \x -> x+1)((\x -> 6) (\x -> x + 1)) ja?
nur damit ichs richtig verstehe.
Ist bei dem teil ((\x -> 6) (\x -> x + 1)) die zweite ano.fkt das argument x der ersten anon. fkt? ja? Aber egal wie die zweite ano.fkt. ausschaut es kommt immer 6 zurück.

> Wieder eingestezt in die ursprüngliche Gleichung
> t3 = (\(x,_,_)->x) (7, \x->x+1, \x->6)

hier ist auch (7, \x->x+1, \x->6) das argument (x,_,_) von der ersten ano.fkt. und die hat als ergebnis wert x also 7. richtig?

Falls ich jetzt alles richtig argumentiert habe, habe ichs glaube ich so irgendwie verstanden. Könntest mir ein kleines ähnliches beispiel geben was ich dann zu lösen versuche ? :)
Zum Seitenanfang    
 
Siracusa

Gepostet:
20.06.2010 19:56

   
> Ist bei dem teil ((\x -> 6) (\x -> x + 1)) die zweite ano.fkt das argument x der ersten anon. fkt? ja? Aber egal wie die zweite ano.fkt. ausschaut es kommt immer 6 zurück.

Ganz genau, normalerweise würde man für die erste Funktion als Parameter einen normalen Wert wie einen Int erwarten, aber da x keine weiteren Anforderungen an einen Typ stellt, kann man hier auch eine Funktion übergeben.

> hier ist auch (7, \x->x+1, \x->6) das argument (x,_,_) von der ersten ano.fkt. und die hat als ergebnis wert x also 7. richtig?

Japp.

> Könntest mir ein kleines ähnliches beispiel geben was ich dann zu lösen versuche ?

Ok, versuch mal das:

u = (\x y -> y x x) 4
v = (\x y z -> (y, x, x z))
w = (\(x,y,z) -> x + y z) (v (\x -> 2*x-1) (u (\x y -> x+x)) 3)


Viel Spaß beim Lösen,

Siracusa
Zum Seitenanfang    
 
constructor

Gepostet:
21.06.2010 01:01

   
Ok ich versuche es mal:

u = (\x y -> y x x) 4
v = (\x y z -> (y, x, x z))
w = (\(x,y,z) -> x + y z) (v (\x -> 2*x-1) (u (\x y -> x+x)) 3)

v nimmt 3 argumente.
das erste ist die funktion (\x -> 2*x-1) das zweite (u(\x y -> x+x) und das dritte 3
phu...

u nimmt zwei argumente das erste ist die funktion (\x y -> x+x). oder ist hier 4 das erste argument?
hm
Zum Seitenanfang    
 
Siracusa

Gepostet:
21.06.2010 18:06

   
> oder ist hier 4 das erste argument?

Ja, der Lambda-Ausdruck ist schon partiell auf 4 angewendet, d.h. u verlangt nur noch ein Argument.
Zum Seitenanfang    
 
constructor

Gepostet:
21.06.2010 18:32

   
> Ja, der Lambda-Ausdruck ist schon partiell auf 4 angewendet, d.h. u verlangt nur noch ein Argument.
aber wie kann 4 das erste argument sien und zugleich ist ja beimaufruf auch \x y -> x+x das erste argument.
ich stell mir das ja immer so vor dass das erste argument x in der ersten zeile durch \x y -> x+x ersetzt wird.
d.h. der die vier wird eigentlich auf die funktion \x y -> x+x angewandt und produziert 8. und zweites argument y gibt es keins.... ?
ist das überhaupt richtig wie ich hier vorgehe?
Zum Seitenanfang    
 
Siracusa

Gepostet:
21.06.2010 19:22

   
Hhm nee, das erste Argument von u ist schon (\x y -> x+x), das erste Argument vom Lambda-Ausdruck in u ist aber 4. Die Ersetzung ist ja folgende: u (\x y -> x+x) == ( (\x y -> y x x) 4 ) (\x y -> x+x). Bei der Auswertung musst du nun erstmal den inneren Lambda-Ausdruck reduzieren, d.h. (\x y -> y x x) auf 4 anwenden, um dann eine neue Funktion zu erhalten, die nun nur noch ein Argument y erwartet.

Du darfst wegen der partiellen Funktionsanwendung in diesem Fall die Argumente aus dem Lambda-Ausdruck nicht direkt in u vorziehen, also u darf nicht so aussehen: u x y = (y x x) 4, dann wäre (\x y -> x+x) tatsächlich der erste Parameter von u und y würde fehlen.
Zum Seitenanfang    
 
constructor

Gepostet:
21.06.2010 19:52

   
> Bei der Auswertung musst du nun erstmal den inneren Lambda-Ausdruck reduzieren, d.h. (\x y -> y x x) auf 4 anwenden, um dann eine neue Funktion zu erhalten, die nun nur noch ein Argument y erwartet.
wenn ich das mache dann ersetze ich x durch 4. somit habe ich eine funktion die als ersten parameter 4 nimmt ja..... was soll das für eine funktion sein.
dann habe ich da stehen \4 y -> y 4 4. der zweite parameter (das y) ist die funktion \x y -> x+x .
d.h. (\4 (\x y -> x+x)) -> \4 4 -> 4 + 4
und das liefert 8.
u(\x y -> x+x) ergibt also 8.
sorry dass ich etwas schwer von begriff bin. aber das grundprinzip dieser ersetzungen raff ich noch nicht.
Zum Seitenanfang    
 
Siracusa

Gepostet:
21.06.2010 22:57

   
> dann habe ich da stehen \4 y -> y 4 4
Also so ist das nicht ganz korrekt, weil das wäre jetzt wiederum eine Funktion, die zwei Parameter erwartet, wobei der erste aber 4 sein muss. Wenn nicht crasht das Programm mit einem Pattern Match-Fehler.

(\x y -> y x x) 4 kann man auch schreiben als (\x -> (\y -> y x x)) 4. Diese Funktion angewendet auf 4 heißt, dass das x als Parameter wegfällt und alle Vorkommen von x durch 4 ersetzt werden. Ergebnis ist also (\y -> y 4 4), eine Funktion die nur noch einen Parameter verlangt (der eine Funktion sein muss), was jetzt genau u entspricht. u angewendet auf (\x y -> x+x) ist also (\y -> y 4 4) angewendet auf (\x y -> x+x), was ((\x y -> x+x) 4 4) ergibt. Da das nun selbst eine Funktionsanwendung ist muss die natürlich auch ausgewertet werden, woraus sich 8 ergibt.

Zugegeben, bei so vielen verschachtelten Lambda-Ausdrücken ist das schon etwas verwirrend, normalerweise geht man mit denen ja auch etwas sparsamer um.
Zum Seitenanfang