www.wikidata.de-de.nina.az
Currying vor allem in der Linguistik auch Schonfinkeln ist die Umwandlung einer Funktion mit mehreren Argumenten in eine Sequenz von Funktionen mit jeweils einem Argument Obwohl das Verfahren 1924 von Moses Schonfinkel 1 erfunden und von Gottlob Frege 2 um 1900 vorausgedacht wurde wird es oft nach Haskell Brooks Curry benannt der das Verfahren 1958 umfangreich theoretisch ausgearbeitet hat 3 Inhaltsverzeichnis 1 Verfahren 2 Beispiele 2 1 Lambda Notation 2 2 Uberladung 2 3 Geometrisches Beispiel 3 Anwendung 3 1 JavaScript 3 2 Java 3 3 Kotlin 3 4 C 3 5 C 3 6 C 3 7 F 3 8 Go 3 9 Haskell 3 10 Python 3 11 Raku 3 12 Ruby 3 13 Scheme 3 14 Tcl 4 Einzelnachweise und AnmerkungenVerfahren BearbeitenEs sei eine Funktion gegeben die n Argumente erfordert Wird diese auf ein Argument angewendet so konsumiert sie nur genau dieses und liefert als Funktionswert eine weitere Funktion die noch n 1 displaystyle n 1 nbsp Argumente verlangt Die zuruckgegebene Funktion wird anschliessend auf alle weiteren Argumente angewendet In Typen ausgedruckt handelt es sich um die Umrechnung einer Funktion f A 1 A n B displaystyle f colon A 1 times ldots times A n to B nbsp zu einer modifizierten Funktion f c u r r i e d A 1 A 2 A n B displaystyle f mathrm curried colon A 1 to A 2 to ldots A n to B ldots nbsp 4 Eine alternative Schreibweise ist curry f f c u r r i e d displaystyle operatorname curry f f mathrm curried nbsp wobei curry displaystyle operatorname curry nbsp als ein Operator verstanden wird der n displaystyle n nbsp stellige Abbildungen fur n gt 1 displaystyle n gt 1 nbsp modifiziert zu einer einstelligen Abbildung deren Bildwerte einstellige Abbildungen sind usw wobei der Reihe nach alle Argumente der ursprunglichen Abbildung durchlaufen werden formal curry A 1 A n B A 1 A 2 A n B displaystyle operatorname curry colon A 1 times ldots times A n to B to A 1 to A 2 to ldots A n to B ldots nbsp Das Konzept des Currying ist verwandt mit aber fur n gt 2 displaystyle n gt 2 nbsp verschieden von dem der partiellen Anwendung wie etwa f a 1 a 2 a n 1 A n B a n f a 1 a 2 a n displaystyle f a 1 a 2 ldots a n 1 cdot colon A n to B a n mapsto f a 1 a 2 ldots a n nbsp f a 1 n 1 mal A 2 A n B a 2 a n f a 1 a 2 a n displaystyle f a 1 underbrace cdot ldots cdot n 1 text mal colon A 2 times ldots times A n to B a 2 dots a n mapsto f a 1 a 2 ldots a n nbsp Im einstelligen Fall n 1 displaystyle n 1 nbsp hat Currying keine Auswirkung f c u r r i e d f displaystyle f mathrm curried f nbsp im zweistelligen Fall n 2 displaystyle n 2 nbsp besteht der Zusammenhang f c u r r i e d A 1 A 2 B a 1 f a 1 displaystyle f mathrm curried colon A 1 to A 2 to B a 1 mapsto f a 1 cdot nbsp d h fur alle a 1 A 1 displaystyle a 1 in A 1 nbsp f c u r r i e d a 1 f a 1 displaystyle f mathrm curried a 1 f a 1 cdot nbsp im dreistelligen Fall n 3 displaystyle n 3 nbsp gilt fur a 1 A 1 displaystyle a 1 in A 1 nbsp f c u r r i e d a 1 A 2 A 3 B a 2 f a 1 a 2 displaystyle f mathrm curried a 1 colon A 2 to A 3 to B a 2 mapsto f a 1 a 2 cdot nbsp und mit zusatzlich a 2 A 2 displaystyle a 2 in A 2 nbsp f c u r r i e d a 1 a 2 A 3 B a 3 f a 1 a 2 displaystyle f mathrm curried a 1 a 2 colon A 3 to B a 3 mapsto f a 1 a 2 cdot nbsp d h f c u r r i e d a 1 a 2 f a 1 a 2 displaystyle f mathrm curried a 1 a 2 f a 1 a 2 cdot nbsp allgemein f c u r r i e d a 1 a 2 a n f a 1 a 2 a n displaystyle f mathrm curried a 1 a 2 dots a n f a 1 a 2 dots a n nbsp f c u r r i e d a 1 a 2 a n 1 f a 1 a 2 a n 1 displaystyle f mathrm curried a 1 a 2 dots a n 1 f a 1 a 2 dots a n 1 cdot nbsp 5 Im Allgemeinen kommt es haufig vor dass eine mehrstellige Abbildung nicht fur alle Wertekombinationen aus den Tragermengen A 1 A n displaystyle A 1 dots A n nbsp definiert ist also nur auf einer Teilmenge des kartesischen Produkts R D f A 1 A n displaystyle R D f subseteq A 1 times cdots times A n nbsp d h auf dem Graphen einer Relation 6 Man kann diese Situation behandeln indem man entweder grundsatzlich partielle Abbildungen zulasst und die obigen Definitionen formal ubernimmt oder man dagegen am Konzept totaler Abbildungen festhalt in letzterem Falle werden die Definitionsbereiche der beteiligten Abbildungen von der Wahl bereits festgelegter Parameter abhangig wie das Beispiel zweistelliger Abbildungen zeigt f c u r r i e d a 1 f a 1 displaystyle f mathrm curried a 1 f a 1 cdot nbsp der Definitionsbereich dieser Abbildung ist von a 1 displaystyle a 1 nbsp abhangig a 2 A 2 a 1 A 1 a 1 a 2 D f R a displaystyle a 2 in A 2 exists a 1 in A 1 colon a 1 a 2 in D f R leftarrow a nbsp also die Urbildfaser von a 1 displaystyle a 1 nbsp bezuglich des als Relation aufgefassten Definitionsbereichs R D f displaystyle R D f nbsp 7 Da fur n 1 gilt f c u r r i e d f displaystyle f mathrm curried f nbsp kann fur f c u r r i e d displaystyle f mathrm curried nbsp dasselbe Symbol verwendet werden wie fur f displaystyle f nbsp Man nennt dies Uberladung siehe auch Signatur Modelltheorie Anmerkungen 8 Beispiele BearbeitenLambda Notation Bearbeiten Ein Beispiel in Lambda Notation soll das Verfahren verdeutlichen wobei die Funktion konkret folgendermassen definiert sei l x y z x y z displaystyle lambda x y z x y z nbsp Die Funktion verlangt also 3 Argumente und gibt diese zuruck Die Definition ist aquivalent zu l x l y l z x y z displaystyle lambda x lambda y lambda z x y z nbsp Bei der Anwendung der Funktion auf die Argumente a b und c geschieht Folgendes l x l y l z x y z a b c D i e A n w e n d u n g displaystyle left lambda x lambda y lambda z x y z right a b c mathsf Die Anwendung nbsp l y l z a y z b c displaystyle left lambda y lambda z a y z right b c nbsp l z a b z c displaystyle left lambda z a b z right c nbsp a b c R e s u l t a t displaystyle a b c mathsf Resultat nbsp Nach erstmaliger Anwendung der Funktion auf a b und c wird x im Funktionskorper durch das erste Argument a ersetzt Das Resultat ist eine Funktion die noch die Argumente y und z verlangt Diese wird sofort auf b und c angewendet Uberladung Bearbeiten Angenommen wir haben eine zweistellige Multiplikationsfunktion mult displaystyle operatorname mult nbsp die zwei naturliche Zahlen multipliziert d h einem Paar naturlicher Zahlen ihr Produkt zuordnet mult N N N m n m n displaystyle operatorname mult colon begin cases mathbb N times mathbb N to mathbb N m n mapsto m n end cases nbsp mit mult m n m n displaystyle operatorname mult m n m n nbsp 9 Per Definition wird diese Funktion auf zwei naturliche Zahlen angewendet und eine naturliche Zahl wird zuruckgegeben beispielsweise mult 2 3 6 displaystyle operatorname mult 2 3 6 nbsp Wird nun zunachst das erste Argument besetzt etwa mit 2 displaystyle 2 nbsp das zweite noch freigelassen entsteht eine einstellige hohere Funktion die selbst ein weiteres Argument aufnimmt und das Produkt mit diesem festen Parameter der Nummer 2 displaystyle 2 nbsp zuruckgibt mult 2 displaystyle operatorname mult 2 cdot colon nbsp N N n 2 n displaystyle begin cases mathbb N to mathbb N n mapsto 2 n end cases nbsp und fur ein beliebiges festes erstes Argument m N displaystyle m in mathbb N nbsp mult m displaystyle operatorname mult m cdot colon nbsp N N n m n displaystyle begin cases mathbb N to mathbb N n mapsto m n end cases nbsp Currying bedeutet nun bei einer n stelligen Funktion diesen Vorgang so lange durchzufuhren bis nur eine noch einstellige hohere Funktion ubrigbleibt Fur n 2 ist daher mult c u r r i e d N N N m mult m displaystyle operatorname mult mathrm curried colon begin cases mathbb N to mathbb N to mathbb N m mapsto operatorname mult m cdot end cases nbsp 10 Da die Bezeichnung mult displaystyle operatorname mult nbsp als einstellige Funktion noch unbesetzt ist kann diese uberladen werden 11 d h im einstelligen Fall wird mult displaystyle operatorname mult nbsp als mult c u r r i e d displaystyle operatorname mult mathrm curried nbsp verstanden mult m n mult c u r r i e d m n mult m n m n displaystyle operatorname mult m n operatorname mult mathrm curried m n operatorname mult m n m n nbsp Geometrisches Beispiel Bearbeiten nbsp f x y x 2 x y y 2Man kann sich die Situation fur eine Funktion mit zwei Argumenten z f x y displaystyle z f x y nbsp wie folgt vorstellen das Fixieren einer Argumentvariable entspricht einer Einschrankung der zweidimensionalen Definitionsmenge auf eine eindimensionale Teilmenge z B y 1 displaystyle y 1 nbsp die resultierende Funktion entspricht der Schnittkurve des Graphen von f x y displaystyle f x y nbsp mit der Ebene aller Punkte x 1 z displaystyle x 1 z nbsp Alle Punkte x y z displaystyle x y z nbsp des Graphen konnen somit auch durch eine zweistufige Auswahl erreicht werden zunachst durch die Festlegung der Schnittebene y 1 displaystyle y 1 nbsp und dann durch die Auswertung der Schnittkurve s x f x y y 1 displaystyle s x f x y y 1 nbsp an der Stelle x displaystyle x nbsp Anwendung BearbeitenCurrying wird uberwiegend in Programmiersprachen und Kalkulen verwendet in denen Funktionen nur ein einzelnes Argument erhalten durfen Dazu gehoren beispielsweise ML Unlambda und der Lambda Kalkul sowie das nach Curry benannte Haskell Viele dieser Sprachen bieten dem Programmierer allerdings syntaktische Moglichkeiten dies zu verschleiern Ein Beispiel hierfur ist die Aquivalenz der Funktionsdefinition im oben gezeigten Beispiel JavaScript Bearbeiten Das nachfolgende Beispiel zeigt Currying in JavaScript Zunachst wird eine Funktion uncurried add definiert die als Ergebnis die Summe der beiden Argumente hat Andererseits wird eine Funktion curried add definiert die eine als Closure definierte Funktion zuruckgibt welche partiell angewendet werden kann function uncurried add x y return x y function curried add x return function y return x y console log uncurried add 3 5 8 console log curried add 3 5 8 const add three curried add 3 console log add three 5 8 console log add three 12 15 Durch Currying wird die Funktion partiell angewendet wobei die Funktionsargumente nacheinander ubergeben werden und zwischenzeitlich in einer neuen Funktion gehalten werden die beliebig weiterverwendet werden kann Die Funktionen konnen in JavaScript mit der Lambda Notation auch kurzer definiert werden const uncurried add x y gt x y const curried add x gt y gt x y Gelaufig ist in JavaScript auch das Currying durch apply eine Methode des Prototyps von Funktionen der ein Kontextobjekt und eine Teilmenge der Parameter ubergeben werden Das Kontextobjekt kann dabei null oder undefined sein und wird dann implizit durch das globale Objekt ersetzt 12 function uncurried add x y return x y const curried add uncurried add bind null 3 console log curried add 5 8 Java Bearbeiten import java util function class Main static IntBinaryOperator uncurriedAdd x y gt x y static IntFunction lt IntUnaryOperator gt curriedAdd x gt y gt x y public static void main String args System out println uncurriedAdd applyAsInt 3 5 8 System out println curriedAdd apply 3 applyAsInt 5 8 var addThree curriedAdd apply 3 System out println addThree applyAsInt 5 8 System out println addThree applyAsInt 12 15 Kotlin Bearbeiten val uncurried add x Int y Int gt x y val curried add x Int gt y Int gt x y println uncurried add 3 5 8 println curried add 3 5 8 val add three curried add 3 println add three 5 8 println add three 12 15 C Bearbeiten C fuhrte den Lambda Kalkul mit anonymen Funktionen in die Sprache ein Mit dem Schlusselwort auto wird durch Typinferenz der Datentyp implizit abgeleitet ohne den Datentypen explizit deklarieren zu mussen Dadurch ergibt sich eine kurzere Schreibweise fur die Currifizierung include lt iostream gt using namespace std int uncurried add int x int y return x y auto curried add int x return x int y return x y int main cout lt lt uncurried add 3 5 lt lt endl 8 cout lt lt curried add 3 5 lt lt endl 8 auto add three curried add 3 cout lt lt add three 5 lt lt endl 8 cout lt lt add three 12 lt lt endl 15 return 0 Man beachte dass die Erwahnung des Typs int im Argument des Lambda Ausdrucks auch durch auto ersetzt werden kann wodurch die Implementierung verallgemeinert wird Die Parameter der benannten Funktion curried add kann jedoch nur durch Templates fur verschiedene Datentypen verallgemeinert werden C BearbeitenDa es in der Programmiersprache C keine anonymen Funktionen gibt wird eine benannte Funktion add separat definiert die von curried add zuruckgegeben wird Der Wert von x wird in der globalen Variablen z gespeichert da die Funktion add nicht auf die Continuation der Funktion curried add zugreifen kann include lt stdio h gt int uncurried add int x int y return x y int z int add int y return y z typedef int function int function curried add int x z x return add int main printf d n uncurried add 3 5 8 printf d n curried add 3 5 8 function add three curried add 3 printf d n add three 5 8 printf d n add three 12 15 return 0 C Bearbeiten using System class Program delegate int Method int x int y delegate Func lt int int gt Curry int x static Method uncurried add x y gt x y static Curry curried add x gt y gt x y public static void Main Console WriteLine uncurried add 3 5 8 Console WriteLine curried add 3 5 8 var add three curried add 3 Console WriteLine add three 5 8 Console WriteLine add three 12 15 F Bearbeiten let uncurried add x y x y let curried add x y x y printfn i uncurried add 3 5 8 printfn i curried add 3 5 8 printfn i curried add 3 5 8 let add three curried add 3 printfn i add three 5 8 printfn i add three 12 15 Go Bearbeiten package main import fmt var uncurried add func a b int int return a b var curried add func a int func a int int return func b int int return a b func main fmt Println uncurried add 2 3 fmt Println curried add 2 3 addThree curried add 3 fmt Println addThree 5 8 fmt Println addThree 12 15 Haskell BearbeitenIn der Programmiersprache Haskell kann eine Funktion nur genau einen Parameter haben Wenn man eine Funktion mit mehreren Argumenten aufrufen mochte mussen die Argumente zuerst in einem neuen Objekt zusammengesetzt werden sodass die Funktion nur ein Argument erhalt Dafur konnen die Parameter in runden Klammern mit Kommata getrennt aufgelistet werden um ein Tupel zu definieren uncurried add x y x yEine Alternative dazu ist das Currying In der expliziten Schreibweise definiert man fur jeden Wert im Tupel jeweils eine Funktion mit nur einem Argument Solange noch nicht alle Argumente ubergeben wurden wird eine Funktion zuruckgegeben die ein Teilergebnis liefert curried add x y gt x yDa die Schreibweise mit mehreren Lambda Funktionen umstandlich sein kann gibt es eine syntaktisch gezuckerte Notation die semantisch aquivalent ist Schreibt man die Argumente ohne runde Klammern hintereinander erhalt man automatisch eine currifizierte Funktion curried add x y x yDie currifizierte Funktion kann sowohl explizit als auch implizit partiell angewendet werden main do print uncurried add 3 5 8 print curried add 3 5 8 print curried add 3 5 8 let add three curried add 3 print add three 5 8 print add three 12 15Zudem gibt es in Haskell die Moglichkeit eine Funktion im Nachhinein zwischen currifizierter und nicht currifizierter Definition umzuwandeln Dafur werden die Funktionen curry und uncurry verwendet main do let uncurried uncurry curried add print uncurried 3 5 8 let curried curry uncurried add print curried 3 5 8 print curried 3 5 8 let add three curried 3 print add three 5 8 print add three 12 15 Python Bearbeiten def uncurried add x y return x y def curried add x return lambda y x y print uncurried add 3 5 8 print curried add 3 5 8 add three curried add 3 print add three 5 8 print add three 12 15 Raku Bearbeiten sub uncurried add x y x y sub curried add x sub y x y say uncurried add 3 5 8 say curried add 3 5 8 my amp add three amp curried add 3 say amp add three 5 8 say amp add three 12 15Es gibt in der Programmiersprache Raku die Moglichkeit ein Funktionsobjekt erst beim Funktionsaufruf zu currifizieren my amp uncurried add sub x y x y say amp uncurried add 3 5 8 say amp uncurried add assuming 3 5 8 my amp add three amp uncurried add assuming 3 say amp add three 5 8 say amp add three 12 15 Ruby Bearbeiten def uncurried add x y return x y end def curried add x return lambda y x y end puts uncurried add 3 5 8 puts curried add 3 call 5 8 add three curried add 3 puts add three call 5 8 puts add three call 12 15Es gibt in der Programmiersprache Ruby die Moglichkeit ein Funktionsobjekt erst beim Funktionsaufruf zu currifizieren uncurried add lambda x y x y puts uncurried add call 3 5 8 puts uncurried add curry 3 5 8 add three uncurried add curry 3 puts add three call 5 8 puts add three call 12 15 Scheme Bearbeiten define uncurried add lambda x y x y define curried add lambda x lambda y x y display uncurried add 3 5 newline 8 display curried add 3 5 newline 8 define add three curried add 3 display add three 5 newline 8 display add three 12 newline 15 Tcl Bearbeiten In Tcl ist es nicht notwendig irgendwelche speziellen Konstrukte als curried oder uncurried Variante vorzubereiten Ein Kommando Aufruf ist in Tcl nur eine Liste von Worten in der das Kommando Wort an erster Position steht Mit dem Operator kann man ein Argument das seinerseits eine Liste ist inplace durch deren Elemente ersetzen Damit kann eine beim Aufruf an vorderster Position stehende Liste neben dem zu rufenden Kommando zusatzlich beliebig viele Argumente in sich tragen Currying ist demzufolge identisch mit dem Anhangen eines weiteren Wortes an diese Liste und jeder mit beginnende Aufruf ist ein Lambda Call Benannt nach den in anderen Sprachen oft Lambda Ausdruck genannten anonymen Funktionen die sich gut auf diese Weise einbinden lassen Zum Addieren ist hier das Standard Kommando tcl mathop verwendet das zur Implementierung der hier nicht benutzten Tcl Expression Syntax existiert Dieses Kommando addiert beliebig viele Argumente Da man solche Experimente sinnvollerweise in der Tcl Konsole anstellt sind hier keine expliziten print Anweisungen notig tcl mathop 3 5 8 direkter Aufruf set f tcl mathop simple Lambda Liste nur das Kommando f 3 5 8 Aufruf uber Lambda in Variable f lappend f 3 Currying durch Hinzufugen set f tcl mathop 3 Curried alternativ direkt formuliert f 5 8 Aufruf uber Curried Lambda lappend f 1 2 mehr Parameter hinzufugen f 4 5 15 3 1 2 4 5 ganz naturlichEinzelnachweise und Anmerkungen Bearbeiten Moses Schonfinkel Uber die Bausteine der mathematischen Logik In Mathematische Annalen 92 1924 S 305 316 Digitalisat Gottlob Frege Grundgesetze der Arithmetik Hermann Pohle Jena 1893 Band I 1903 Band II korpora org Haskell Brooks Curry Robert Feys Roger Hindley Jonathan P Seldin Combinatory Logic North Holland 2 Bande 1958 1972 Dabei bezeichnet X Y displaystyle X to Y nbsp oder X Y displaystyle X to Y nbsp die Menge der Abbildungen von X displaystyle X nbsp nach Y displaystyle Y nbsp Im nullstelligen Fall n 0 wurde das Currying einer Abbildung f displaystyle f nbsp ohne Parameter und mit einem Wert b B displaystyle b in B nbsp eine einstellige Abbildung mit konstantem Wert b displaystyle b nbsp zuordnen also etwa f c u r r i e d B B x b displaystyle f mathrm curried colon B to B x mapsto b nbsp Ein Beispiel ist f a 1 a 2 a 1 a 1 a 2 displaystyle f a 1 a 2 a 1 a 1 a 2 nbsp mit a 1 a 2 R D R displaystyle a 1 a 2 in mathbb R setminus Delta mathbb R nbsp wobei D R displaystyle Delta mathbb R nbsp die Diagonale a 1 a 2 R 2 a 1 a 2 displaystyle a 1 a 2 in mathbb R 2 a 1 a 2 nbsp bezeichnet Im obigen Beispiel ist dies R a 1 displaystyle mathbb R setminus a 1 nbsp Voraussetzung ist dass das Symbol f displaystyle f nbsp nicht schon anderweitig mit Stelligkeit 1 uberladen ist siehe Beispiel unten dies zwingt zwischen mult displaystyle operatorname mult nbsp und prod displaystyle operatorname prod nbsp zu unterscheiden Zur Unterscheidung vom Platzhalter displaystyle cdot nbsp wird hier displaystyle nbsp als Multiplikationszeichen verwendet Dieser Funktion konnte man auch einen eigenen Namen vergeben doppelt mult c u r r i e d 2 mult 2 N N displaystyle operatorname doppelt operatorname mult mathrm curried 2 operatorname mult 2 cdot colon mathbb N to mathbb N nbsp mit doppelt n 2 n displaystyle operatorname doppelt n 2 n nbsp Man unterscheide zwischen mult displaystyle operatorname mult nbsp und der uberladenen Funktion prod displaystyle operatorname prod nbsp mit prod k 1 k r i 1 r k i displaystyle operatorname prod k 1 dotsc k r prod i 1 r k i nbsp zur Stelligkeit r displaystyle r nbsp und Faktoren k i N displaystyle k i in mathbb N nbsp Zwar ist zweistellig mult m n prod m n m n displaystyle operatorname mult m n operatorname prod m n m n nbsp aber einstellig ist prod m m displaystyle operatorname prod m m nbsp wahrend mult m mult c u r r i e d m mult m displaystyle operatorname mult m operatorname mult mathrm curried m operatorname mult m cdot nbsp eine einstellige Funktion ist Kyle Simpson this amp Object Prototypes In You Don t Know JS 1 Auflage Band 3 O Reilly 2014 ISBN 978 1 4919 0415 2 S 26 28 Abgerufen von https de wikipedia org w index php title Currying amp oldid 236669067