Die übergabe-Liste, die Elemente, die als Parameter an Curry-Funktion
Immer noch eine Haskell-newbie hier. Ich weiß gerade genug, um mich in Schwierigkeiten mit falschen Annahmen. Wenn ich die folgende Funktion...
quadsum w x y z = w+x+y+z
Möchte ich eine Funktion, die eine Liste, verwenden Sie jedes element als parameter in einer bestimmten Funktion wie quadsum
, und zurückgeben einer Curry-Funktion für die spätere Verwendung.
Ich habe versucht etwas zu der Wirkung von...
magicalFunctionMaker f [] = (f)
magicalFunctionMaker f (x:xs) = magicalFunctionMaker (f x) xs
Mit der Hoffnung, in der Lage, dies zu tun...
magicalFunctionMaker (quadsum) [4,3,2]
Immer eine Curry-Funktion wie...:
(((quadsum 4) 3) 2)
Oder, alternativ, rufen Sie:
magicalFunctionMaker (quadsum) [4,3,2,1]
Was in...
((((quadsum 4) 3) 2) 1)
Ist das möglich? Wie fehlgeleitet bin ich?
Ein kurzer Blick auf polyvariadic Funktionen, aber es kann blow your mind: [stackoverflow.com/questions/3467279/...
InformationsquelleAutor Ishpeck | 2010-09-23
Schreibe einen Kommentar Antworten abbrechen
Du musst angemeldet sein, um einen Kommentar abzugeben.
Paul Johnson ' s Antwort deckt ziemlich genau. Nur tun
und das Ergebnis wird der Funktion, die Sie möchten, geben Sie
Integer -> Integer
.Aber manchmal nicht gut genug ist. Manchmal findet man Listen von zahlen, die Sie nicht wissen, wie lang die Listen sind, und Sie müssen, um die Elemente auf Ihre Funktion. Das ist ein bisschen schwieriger. Sie nicht tun können:
weil die Ergebnisse, die verschiedene Typen haben. Im ersten Fall ist das Ergebnis braucht zwei Argumente, und in der zweiten es ist ein voll-Funktion angewendet, so dass keine Argumente mehr, die sind erlaubt. In diesem Fall, das beste, was zu tun ist, halten Sie auf der Liste, und Ihre ursprüngliche Funktion, bis genügend Argumente vorhanden sind:
können Sie jetzt tun:
Benötigen Sie einen separaten vereinfachen-Funktion für jede stelligkeit, ein problem, das den meisten leicht behoben, indem die Template Haskell.
Verwendung von Listen von Argumenten, (im Gegensatz zu einem argument von Listen) neigt dazu, sehr umständlich in Haskell, weil die mehrere Ergebnisse haben alle unterschiedliche Arten, und es gibt sehr wenig Unterstützung für Kollektionen mit variabler Anzahl von unterschiedlich typisierte Argumente. Ich habe gesehen, drei Allgemeine Kategorien von Lösungen:
Explizit code für jeden Fall
separat (wird schnell sehr viel
Arbeit).
Template Haskell.
Typ system Hack.
Meine Antwort meist befasst sich mit dem Versuch um 1 weniger schmerzhaft. 2 und 3 sind nicht für das schwache des Herzens.
Edit: Es stellt sich heraus, dass es einige Pakete auf Hackage, die im Zusammenhang mit diesem problem. Mit "iteratee":
Aber "iteratee" und "enumerator" sind wahrscheinlich overkill, aber.
In the first case the result needs two arguments
- sollte dies nichtneeds one argument
-4 3 2
muss1
?InformationsquelleAutor John L
Ich denke, Sie sind Missverständnis, das Haskell Typ-system.
Sind vor allem Ihre "quadsum" - Funktion ist Curry schon. Sie können schreiben, "quadsum 4 3" und wieder eine Funktion, die erwartet, dass die 2 und die 1 als zusätzliche Argumente. Wenn Sie schreiben "quadsum 4 3 2 1", das ist gleichbedeutend mit "((((quadsum 4) 3) 2) 1)".
In Haskell eine Liste von Ganzzahlen hat eine andere Art, eine ganze Zahl oder ein Tupel wie "(4,3,2,1)". Vor diesem hintergrund ist es eher schwierig zu verstehen, was Sie versuchen zu tun. Was soll passieren, wenn Sie schreiben?
Ihre "magicalFunctionMaker" wirkt eher wie "foldl", mit der Ausnahme, dass die Funktion, die Sie geben, um foldl nimmt nur zwei Argumente. So können Sie schreiben:
Dieser gibt eine Funktion, die eine Liste und Summen der Elemente.
(BTW, sobald Sie verstehen lernen, was der Unterschied zwischen foldl und foldr.
Edit:
Haben re-Lesen Sie Ihre Frage, ich denke, Sie versuchen, Sie zu bekommen:
Dies ist unmöglich, weil die Art der magicalFunctionMaker würde, hängt von der Länge der Liste-argument, das würde bedeuten, dynamische Typisierung. Als jemand sagte, polyvariadic Funktionen tun können, so etwas wie dies (wenn auch nicht mit einer Liste argument), aber das erfordert schon ein paar milli-olegs vom Typ Hack.
InformationsquelleAutor Paul Johnson
Kam ich bis vor das gleiche problem: ich habe eine Funktion wie
Was ich gerne tun würde ist eine Magische Funktion, so dass zum Beispiel
so, dass ich sagen kann,
Instinktiv, wie es scheint, und John ' s Antwort stimmt, dass es möglich sein sollte, zu tun einige Art-system magic, um dies zu tun. Es gibt Lösungen für ähnliche Probleme, die machen explizit iso-rekursive Datentypen-mit einem Bündel von expliziten rolling and unrolling (siehe, z.B., Kapitel 20 von Typen und Programmiersprachen, oder der 4. post in dieser thread).
Ich hackte auf die Art-Lösung für eine Weile, es fühlt sich möglich, aber ich habe es nicht ganz verstanden zu arbeiten, bevor Sie entscheiden, zu versuchen, Template Haskell, und es gibt Dinge, die sind viel freundlicher.
(Erinnere mich an die SPRACHE zu verwenden, pragma oder -XTemplateHaskell Kommandozeilen-Schalter.)
Diesen zu nutzen, rufen Sie lApply innerhalb einer splice-wie so:
Beachten Sie, dass ich eine string mit dem Namen der Funktion möchte ich nennen: ich kann nicht heben eine Funktion direkt in eine ExpQ, aber ich kann beziehen sich auf seinen globalen Bindung. Ich kann sehen, wie könnte dies ärgerlich. Auch, weil der Weg, den wir Durchlaufen die Liste, Argumente müssen dargestellt werden in umgekehrter Reihenfolge in der Liste.
Gibt es ein paar andere Falten: um verallgemeinern zu anderen Datentypen, die diese Typen haben, um die entsprechenden Instanzen in der Lift-Klasse. Zum Beispiel, Doppelklicken Sie hat keine Instanz, aber Sie können leicht machen eine:
Aufleuchten der Datentyp nicht über eine DoubleL-Konstruktor, sondern RationalL kann an seiner Stelle verwendet werden, da es werde Spleißen, um ein Allgemeines Mitglied von der Bruch-Klasse.
Wenn Sie dies nutzen wollen, mit Funktionen, die eine Mischung von Typen als Argumente haben, werden Sie nicht in der Lage zu gehen eine Liste, da die Listen nicht von gemischten Typen. Sie könnte verwenden Tupeln, die dies tun, das ist ehrlich gesagt nicht viel schwerer mit Template Haskell. In diesem Fall würden Sie eine Funktion erzeugt, dass der AST einer Funktion, die ein Tupel mit den entsprechenden Typen innerhalb und ordnet Sie dem Aufruf der Funktion, die Sie wollen. Alternativ können Sie wickeln Sie Ihre argument-Typen innerhalb einer entsprechend gestalteten ADT, der übrigens könnte man auch erstellen mit Template Haskell. Dies bleibt als übung für den Leser 🙂
Schließlich alle von der standard-Template-Haskell-Beschränkungen gelten. Zum Beispiel, Sie können nicht rufen Sie diese Funktion aus dem Modul, wo Sie definiert ist, weil der GHC Bühne Einschränkung.
Template Haskell ist Spaß und interessante Sachen, aber um ganz ehrlich zu sein die iso-rekursiven Datentyp Lösung ist wahrscheinlich ein bisschen mehr Leistung, und offensichtlich nicht erfordern den zusätzlichen Einsatz von TH. Ich werde wiederkommen und post ein follow-up, falls/wenn ich verstehe, dass Sie arbeiten 🙂
InformationsquelleAutor kwantam
Können Sie nicht einmal eine Liste der Fälle, für die unterschiedliche Länge "manuell":
Das bedeutet, dass mf nicht nehmen eine Funktion der willkürlichen "stelligkeit", Sie haben sich für eins entscheiden. Aus dem gleichen Grund Sie können nicht konvertieren eine beliebige Liste in ein Tupel: Man kann nicht sagen, wie viele Elemente die Tupel wird halten, aber der Typ system wissen muss.
Könnte es eine Lösung sein, durch die Begrenzung f um eine rekursive Typ a = a -> durch Verwendung von "füralle" (siehe http://www2.tcs.ifi.lmu.de/~abel/fomega/hm.html). Aber ich konnte es nicht funktioniert (es scheint, muss ich sagen, Leksah, verwenden Sie die flag -XRankNTypes irgendwo), und dass die Beschränkung auf f machen würde, Ihre Funktion ziemlich nutzlos.
[Bearbeiten]
Denken, ist die nächste Sache, was, die Sie wollen, ist wahrscheinlich irgendeine Art von reduce-Funktion. Als Paul wies darauf hin, dies ist ähnlich zu foldl, foldr... (aber die version unten ist ohne "extra Arguments" und eine homogene Art, die im Vergleich zu foldl. Beachten Sie die fehlende base-case für leere Listen)
InformationsquelleAutor Landei
Nicht zur Arbeit zu gehen, denke ich.
(((quadsum 4) 3) 2)
hat eine andere ArtIntger -> Integer
zum Beispiel als((((quadsum 4) 3) 2) 1)
die eine Art vonInteger
.InformationsquelleAutor user268396
War ich zu Bearbeiten meinem anderen Beitrag, aber dieser ist groß genug, für seine eigenen.
Hier ist ein Weg, es zu tun mit "Art magic", aber es fühlt sich für mich wie es ist etwas suboptimal, da es erfordert eine Hebe-Funktion, die bestimmte Funktionen zu einer bestimmten Anzahl von Argumenten (mehr dazu weiter unten).
Beginnen wir mit der Definition einer rekursiven Datentyp
Also Variablen vom Typ RecT kann entweder nur gewickelt Ergebnis (RecR), oder Sie kann eine Fortsetzung der Rekursion (Reg.).
Nun,wie nehmen wir etwas und wirf es in Typ RecT ein?
Werte sind ganz einfach:
RecR x ist offensichtlich vom Typ RecT ein.
Was ist eine Funktion, die ein argument, wie die id?
Reg. umschließt eine Funktion, eine variable und gibt den Typ RecT ein. Der Ausdruck
ist so eine Funktion, da wir beobachten, bevor RecR x ist vom Typ RecT ein.
Allgemein alle ein-argument-Funktion kann aufgehoben werden:
Können wir verallgemeinern dies durch mehrfaches wickeln mehr tief verschachtelte Funktionsaufrufe innerhalb Reg.:
OK, also wir haben alles getan, dieses Werk wiederum eine Funktion von einer beliebigen Anzahl von Argumenten in einer Art, RecT ein. Wie verwenden wir diese?
Können wir leicht schreiben Sie eine Ebene der Funktion Anwendung:
In anderen Worten, reduceRecT nimmt ein argument vom Typ RecT und ein anderer Typ ein und gibt ein neues Rechteck ein, das ist schon eine Ebene reduziert.
Wir können auch entrollen Sie eine fertige Berechnung innerhalb einer RecT-in der Folge:
Nun sind wir bereit, um eine Liste von Argumenten an eine Funktion!
Betrachten wir die base-case-Erstens: wenn wir fertig mit der Berechnung, die wir nur wickeln Sie das Ergebnis und gibt es zurück. Im rekursiven Fall, reduzieren wir die Liste der Argumente durch, dann verwandeln Sie die fn durch die Anwendung der Spitze der Liste der reduzierten fn, woraus ein neues RecT ein.
Let ' s probieren:
So, Vorteile und Nachteile hat dieser Ansatz? Gut, das Template Haskell-version tun können unvollständige Liste Anwendung; dies gilt nicht für die isorecursive Art Lösung wie hier vorgestellt, (obwohl wir im Prinzip könnte dieses Problem beheben mit einigen Hässlichkeit). Die Lösung hat auch den Nachteil, dass Sie viel mehr boilerplate-code zugeordnet: brauchen wir eine listNRecT für alle N, die wir verwenden wollen. Endlich, es ist viel weniger einfach zu verallgemeinern, um die Analog-Tupel Lösung, wenn wir wollen lApply zu Funktionen, die von gemischten Variablen-Typen.
Natürlich, eine weitere interessante Möglichkeit ist die Verbesserung Kürze durch die Verwendung von Template Haskell zu generieren, die listNRecT Funktionen; dieses beseitigt einige boilerplate, aber in einem Sinne, kauft die Nachteile der beiden Implementierungen.
InformationsquelleAutor kwantam