Wie lautet diese Funktion, um das letzte Element in einer Liste zu erhalten?

8

Nach Abschluss des ersten Problems (" Finden Sie das letzte Element einer Liste ") in der 99 Fragen Übungen , ich wollte sehen, wie meine Lösung im Vergleich zu anderen und ich fand diese Lösung .

%Vor%

Diese Dokumentation scheint zu zeigen, dass foldr1 zwei Argumente benötigt, wobei das erste eine Funktion ist und der zweite ist eine Liste. Aber diese Definition scheint nur eine Funktion als Argument zu haben. Gibt es eine implizite Definition der Argumente, die so übergeben werden?

%Vor%

Ich habe die Definitionen von foldr1 , const und id nachgeschlagen, aber es fällt mir schwer zu verstehen, wie diese drei zusammenarbeiten, um das letzte Element in der Liste zurückzugeben.

    
Cory Klein 03.09.2013, 17:24
quelle

4 Antworten

6

Sie sind genau richtig. In Haskell kann eine Funktion, die zwei Argumente akzeptiert, tatsächlich als eine Funktion behandelt werden, die ein Argument verwendet und eine andere Funktion zurückgibt, die ein Argument verwendet. dies wird als currying bezeichnet. Beachten Sie, dass die Funktionssignatur für foldr1 lautet:

%Vor%

Während wir es oft als "eine Funktion betrachten, die eine Funktion und eine Liste als Argumente akzeptiert und einen Wert zurückgibt", ist es in Wirklichkeit eine Funktion, die eine Funktion als Argument akzeptiert und eine Funktion zurückgibt, die eine Liste übernimmt und zurückgibt ein Wert ".

    
mipadi 03.09.2013 17:30
quelle
3

Wie Mipadi erklärt, wird die Funktion curried. Das erklärt, wie das Listenargument dort ankommt, erklärt aber vielleicht nicht, wie die tatsächliche Faltung funktioniert.

Das const id -Bit ist ein wenig trixy. foldr1 erwartet, etwas vom Typ a -> a -> a zu erhalten. Die Definitionen dieser Funktionen sind

%Vor%

Also, alles zusammen vermasselnd, haben wir

%Vor%

In der Reihenfolge der Wörter macht const id dasselbe wie flip const ; Es ist eine 2-Argument-Funktion, die das erste Argument wegwirft und das zweite zurückgibt. Es ist nicht sehr offensichtlich, dass das so ist; IMHO, flip const wäre klarer.

foldr1 ruft diese Funktion mit dem alten Wert als erstem Argument und dem nächsten Listenelement als zweitem Argument auf. Diese Funktion gibt immer das nächste Listenelement zurück. Die endgültige Ausgabe von foldr ist die letzte Ausgabe der Funktion, die das letzte Element der gesamten Liste ist.

    
MathematicalOrchid 03.09.2013 18:24
quelle
0

Ja, Ihre Intuition über Funktionen, die nicht alle Argumente benötigen, ist genau richtig. Und wenn eine Funktion eine andere Funktion als einen Parameter verwendet, um als Ergebnis eine andere Funktion zurückzugeben, wird sie "currying" genannt. Siehe: Ссылка .

(Als Randnotiz wurde dies tatsächlich von Haskell Curry entdeckt (oder wiederentdeckt), und so hat unser Haskell seinen Namen bekommen.)

Wenn die Idee des Currys noch Zeit braucht, um zu sinken, kann dies helfen: Es gibt tatsächlich zwei Funktionen, die in Prelude namens curry und uncurry definiert sind. Sie tragen die folgenden Typen:

%Vor%

uncurry verwendet eine 2-Argument curried -Funktion (oder eine Funktion, die eine Funktion eines Arguments übernimmt, das eine Funktion eines Arguments zurückgibt) und erzeugt ein uncurrried Funktion oder eine Funktion, die alle Argumente alle auf einmal (als Tupel.)

verwendet

curry , wie Sie mit dem Namen und seinem Typ sagen können, geht in die andere Richtung, so dass es eine curried Funktion (eine Funktion, die alle Argumente auf einmal nimmt) und erzeugt eine Funktion, die ein Argument benötigt und eine Funktion zurückgibt, die das andere Argument übernimmt.

Die meisten Programmiersprachen arbeiten standardmäßig unbeirrt, Sie stellen alle Argumente zur Verfügung und erhalten ein Ergebnis, während Haskell standardmäßig voreingestellt ist.

Als Beispiel für uncurry können wir eine einfache Funktion verwenden, (+) :

%Vor%

Und wir könnten das auch mit const machen, wenn wir wollen:

%Vor%

Aber eine uncurried-Version von const ist einfach nicht sehr nützlich, weil es keinen Sinn hat, eine Funktion zu haben, die zwei Argumente akzeptiert und immer die erste zurückgibt, wenn Sie alle Argumente im voraus angeben müssen.

const ist gerade deshalb nützlich, weil es curried ist und an einer Stelle angegeben werden kann, an der eine Funktion benötigt wird, die zwei Argumente benötigt und einfach die erste zurückgibt.

Wie in foldr1 , zum Beispiel:

%Vor%

Wo das erste Argument eine Curry-Funktion von zwei Argumenten ist. Und da der Rückgabewert einer Funktion eine Funktion sein kann, kann dies auch mit const sein:

%Vor%

const id nimmt einfach ein Argument eines beliebigen Typs b und gibt die Funktion id zurück.

Also, wenn wir const id Schritt für Schritt anwenden können:

%Vor%

const id 1 oder const id anyOtherValueHere gibt nur die ID-Funktion zurück. Welche kann so verwendet werden:

%Vor%

Also ignoriert const wirklich das zweite Argument. Direkt darüber verhält sich id wie 100.

Also nimmt foldr1 (const id) einfach eine Liste und wendet id auf jede Menge von zwei Elementen an und behält die zweite (weil const id den Wert von id für das zweite übergebene Argument zurückgibt) bis wir habe das letzte Element.

    
dg123 03.09.2013 18:44
quelle
0

Sie haben Recht, dass Ihre beiden Beispiele durcheinander ersetzt werden können. Dies kann man sich wie in der Algebra-Klasse als algebraische Annullierung vorstellen.

%Vor%

Ich kann die y auf jeder Seite abbrechen:

%Vor%

Jetzt kann ich das x auf jeder Seite abbrechen:

%Vor%

Schauen Sie sich die Wiki-Seite für foldr vs foldl und foldl an , um ein wenig mehr über foldr zu erfahren .

Um eine Vorstellung davon zu bekommen, wie myLast funktioniert, können wir etwas algebraische Suptation durchführen.

%Vor%

Nun sollten wir die Definition von% co_de verwenden % insbesondere: foldr1

%Vor%

foldr1 f (x:xs) = f x (foldr1 f xs) hat den Typ sig const id , der mit b -> a -> a identisch ist, und es stellt sich heraus, dass es genauso funktioniert, was eine Funktion ist, die das erste Argument ignoriert und das zweite Argument zurückgibt. Beispiel: flip const * siehe unten für ein wenig mehr *

%Vor%

Dieser letzte Schritt ist möglicherweise nicht das, was Sie erwartet haben, aber wenn Sie die Definition von (const id) 1 3 == 3 überprüfen, enthält sie:

%Vor%

Welches Muster passt zusammen, wenn es nur ein Element in der Liste gibt, und gibt es zurück.

* Wie funktioniert foldr1 ?

const id gibt das erste Argument zurück und ignoriert es als zweites

%Vor%     
Davorak 03.09.2013 18:30
quelle

Tags und Links