Curry przekształca pojedynczą funkcję z n argumentów w n funkcji z jednym argumentem każdy. Biorąc pod uwagę następującą funkcję:
function f(x,y,z) { z(x(y));}
Po curry staje się:
function f(x) { lambda(y) { lambda(z) { z(x(y)); } } }
Aby uzyskać pełne zastosowanie f (x, y, z), musisz to zrobić:
f(x)(y)(z);
Wiele funkcjonalnych języków pozwala pisać f x y z
. Jeśli wywołujesz f x y
lub f (x) (y), to otrzymujesz częściowo zastosowaną funkcję - zwracana wartość to zamknięcie lambda(z){z(x(y))}
z przekazanymi wartościami x i y do f(x,y)
.
Jednym ze sposobów użycia aplikacji częściowej jest zdefiniowanie funkcji jako aplikacji częściowej funkcji uogólnionych, takich jak fold :
function fold(combineFunction, accumulator, list) {/* ... */}
function sum = curry(fold)(lambda(accum,e){e+accum}))(0);
function length = curry(fold)(lambda(accum,_){1+accum})(empty-list);
function reverse = curry(fold)(lambda(accum,e){concat(e,accum)})(empty-list);
/* ... */
@list = [1, 2, 3, 4]
sum(list) //returns 10
@f = fold(lambda(accum,e){e+accum}) //f = lambda(accumulator,list) {/*...*/}
f(0,list) //returns 10
@g = f(0) //same as sum
g(list) //returns 10
Najłatwiejszym sposobem sprawdzenia, jak się różnią, jest rozważenie prawdziwego przykładu . Załóżmy, że mamy funkcję,
Add
która przyjmuje 2 liczby jako dane wejściowe i zwraca liczbę jako dane wyjściowe, np .Add(7, 5)
Zwraca12
. W tym przypadku:Częściowe zastosowanie funkcji
Add
z wartością7
da nam nową funkcję jako wynik. Sama funkcja przyjmuje 1 liczbę jako dane wejściowe i zwraca liczbę. Takie jak:Więc możemy to zrobić:
Wybranie tej funkcji
Add
da nam nową funkcję jako wynik. Sama funkcja przyjmuje 1 liczbę jako dane wejściowe i wyjściowe jeszcze jedną nową funkcję. Ta trzecia funkcja przyjmuje następnie 1 liczbę jako dane wejściowe i zwraca liczbę jako dane wyjściowe. Takie jak:Więc możemy to zrobić:
Innymi słowy, „curry” i „częściowe zastosowanie” to dwie zupełnie różne funkcje. Curry wymaga dokładnie 1 danych wejściowych, podczas gdy częściowa aplikacja wymaga 2 (lub więcej) danych wejściowych.
Mimo że oba zwracają funkcję jako wynik, zwrócone funkcje mają zupełnie inne formy, jak pokazano powyżej.
źródło
n-ary
na(x - n)-ary
, curry zn-ary
nan * 1-ary
. Częściowo zastosowana funkcja ma ograniczony zakres (zastosowania), co oznacza, żeAdd7
jest mniej wyrazista niżAdd
. Z drugiej strony funkcja curry jest równie wyrazista jak funkcja oryginalna.f2(7)(5) is just a syntactic shortcut
? (Wiem bardzo mało.) Nief2
zawiera / „wie o” 7?curry
implementacja (nie myśl, że to jestfunctools
)Uwaga: zostało to zaczerpnięte z F # Basics doskonałego artykułu wprowadzającego dla programistów .NET, którzy zaczynają programować funkcjonalnie.
źródło
Interesujące pytanie. Po krótkich poszukiwaniach „Aplikacja częściowo funkcjonująca nie curry” podała najlepsze znalezione wyjaśnienie. Nie mogę powiedzieć, że praktyczna różnica jest dla mnie szczególnie oczywista, ale nie jestem ekspertem od FP…
Inną przydatną stroną (której przyznam, że jeszcze nie przeczytałem w pełni) jest „Currying and Partial Application with Java Closures” .
Wygląda na to, że to bardzo myląca para terminów.
źródło
Odpowiedziałem na to w innym wątku https://stackoverflow.com/a/12846865/1685865 . Krótko mówiąc, aplikacja funkcji częściowej polega na naprawianiu niektórych argumentów danej funkcji wielowymiarowej, aby uzyskać inną funkcję z mniejszą liczbą argumentów, natomiast Currying polega na przekształceniu funkcji N argumentów w funkcję jednoargumentową, która zwraca funkcję jednoargumentową ... [Przykład Curry pokazano na końcu tego postu.]
Curry ma przede wszystkim znaczenie teoretyczne: obliczenia można wyrażać przy użyciu tylko jednoargumentowych funkcji (tj. Każda funkcja jest jednoargumentowa). W praktyce i jako produkt uboczny, jest to technika, która może uczynić wiele przydatnych (ale nie wszystkich) częściowych aplikacji funkcjonalnych trywialnymi, jeśli język ma funkcje curry. Ponownie, nie jest to jedyny sposób na wdrożenie częściowych aplikacji. Możesz więc spotkać się ze scenariuszami, w których częściowe stosowanie odbywa się w inny sposób, ale ludzie mylą to jako curry.
(Przykład curry)
W praktyce nie pisze się tylko
lub równoważny javascript
zamiast
ze względu na Curry.
źródło
Curry jest funkcją jednego argumentu, który przyjmuje funkcję
f
i zwraca nową funkcjęh
. Zauważ, żeh
pobiera argumentX
i zwraca funkcję, która jest odwzorowanaY
naZ
:Częściowa aplikacja jest funkcją dwóch (lub więcej) argumentów, która pobiera funkcję
f
i jeden lub więcej dodatkowych argumentówf
i zwraca nową funkcjęg
:Zamieszanie powstaje, ponieważ przy funkcji dwóch argumentów zachowana jest następująca równość:
Obie strony uzyskają tę samą funkcję jednego argumentu.
Równość nie jest prawdziwa dla funkcji wyższego rzędu, ponieważ w tym przypadku curry zwróci funkcję jednego argumentu, podczas gdy częściowa aplikacja zwróci funkcję wielu argumentów.
Różnica polega także na zachowaniu, podczas gdy curry przekształca rekurencyjnie całą oryginalną funkcję (jeden raz dla każdego argumentu), częściowe zastosowanie jest tylko krokiem zastępczym.
Źródło: Wikipedia Currying .
źródło
Różnicę między curry a częściową aplikacją można najlepiej zilustrować za pomocą następującego przykładu JavaScript:
Częściowe zastosowanie skutkuje funkcją mniejszego arsenału; w powyższym przykładzie
f
ma arity 3, apartial
ma arity 2. Co ważniejsze, częściowo zastosowana funkcja zwróci wynik natychmiast po wywołaniu , a nie kolejna funkcja w łańcuchu curry. Więc jeśli widzisz coś takiegopartial(2)(3)
, w rzeczywistości nie jest to częściowe zastosowanie.Dalsza lektura:
źródło
Prosta odpowiedź
Curry: pozwala wywoływać funkcję, dzieląc ją na wiele wywołań, zapewniając jeden argument na wywołanie.
Częściowe: pozwala wywołać funkcję, dzieląc ją na wiele wywołań, zapewniając wiele argumentów na wywołanie.
Proste wskazówki
Oba pozwalają na wywołanie funkcji dostarczającej mniej argumentów (lub, lepiej, dostarczając je łącznie). W rzeczywistości oba z nich wiążą (przy każdym wywołaniu) określoną wartość z określonymi argumentami funkcji.
Rzeczywistą różnicę można zauważyć, gdy funkcja ma więcej niż 2 argumenty.
Proste e (c) (próbka)
(w JavaScript)
dlaczego zawsze przekazuje argumenty, takie jak kontekst i wywołania zwrotne, jeśli zawsze będą takie same? Po prostu przypisz kilka wartości dla funkcji
i nazwij to temat1 i foobar z
Wygodne, prawda? 😉
Z curry trzeba będzie przekazywać jeden argument na raz
Zrzeczenie się
Pominąłem wszystkie wyjaśnienia akademickie / matematyczne. Bo ja tego nie wiem. Może to pomogło 🙃
źródło
Miałem to pytanie podczas nauki i od tego czasu zadawano mi je wiele razy. Najprostszym sposobem na opisanie różnicy jest to, że oba są takie same :) Pozwólcie, że wyjaśnię ... są oczywiście różnice.
Zarówno częściowe zastosowanie, jak i curry wymagają podania argumentów funkcji, być może nie wszystkich naraz. Dość kanonicznym przykładem jest dodanie dwóch liczb. W pseudokodzie (właściwie JS bez słów kluczowych) podstawowa funkcja może być następująca:
Gdybym chciał funkcji „addOne”, mógłbym ją częściowo zastosować lub curry:
Teraz korzystanie z nich jest jasne:
Jaka jest różnica? Cóż, jest subtelny, ale częściowa aplikacja wymaga podania pewnych argumentów, a zwrócona funkcja wykona główną funkcję przy następnym wywołaniu, podczas gdy currying będzie czekał, aż będzie miał wszystkie niezbędne argumenty:
Krótko mówiąc, użyj częściowej aplikacji do uzupełnienia niektórych wartości, wiedząc, że przy następnym wywołaniu metody zostanie ona wykonana, pozostawiając niezdefiniowane wszystkie niedostarczone argumenty; używaj curry, jeśli chcesz stale zwracać częściowo zastosowaną funkcję tyle razy, ile jest to konieczne do wypełnienia podpisu funkcji. Ostatni wymyślony przykład:
Mam nadzieję że to pomoże!
AKTUALIZACJA: Niektóre implementacje języków lub bibliotek lib pozwolą ci przekazać arity (całkowitą liczbę argumentów w końcowej ocenie) do częściowej implementacji aplikacji, co może złączyć moje dwa opisy w mylący bałagan ... ale w tym momencie obie techniki są w dużej mierze wymienne.
źródło
Dla mnie aplikacja częściowa musi utworzyć nową funkcję, w której użyte argumenty są całkowicie zintegrowane z funkcją wynikową.
Większość języków funkcjonalnych implementuje curry, zwracając zamknięcie: nie oceniaj pod lambda, gdy zostanie częściowo zastosowane. Tak więc, aby częściowe zastosowanie było interesujące, musimy wprowadzić różnicę między curry a częściowym zastosowaniem i rozważyć częściowe zastosowanie jako curry plus ocena pod lambda.
źródło
Mogę się bardzo mylić, ponieważ nie mam silnego doświadczenia w matematyce teoretycznej lub programowaniu funkcjonalnym, ale z mojej krótkiej wyprawy do FP wydaje się, że curry ma tendencję do przekształcania funkcji N argumentów w N funkcji jednego argumentu, podczas gdy częściowe zastosowanie [w praktyce] działa lepiej z funkcjami wariadycznymi z nieokreśloną liczbą argumentów. Wiem, że niektóre przykłady z poprzednich odpowiedzi są sprzeczne z tym wyjaśnieniem, ale pomogło mi to najbardziej w rozróżnieniu pojęć. Rozważ ten przykład (napisany w CoffeeScript za zwięzłość, przepraszam, jeśli będzie on mylący, ale w razie potrzeby poproś o wyjaśnienie):
Jest to oczywiście wymyślony przykład, ale zauważ, że częściowe zastosowanie funkcji, która akceptuje dowolną liczbę argumentów, pozwala nam wykonać funkcję, ale z pewnymi wstępnymi danymi. Curryowanie funkcji jest podobne, ale pozwala nam wykonać funkcję parametru N w kawałkach, dopóki wszystkie N parametrów nie zostaną uwzględnione.
Ponownie, to moje zdanie z rzeczy, które przeczytałem. Jeśli ktoś się nie zgadza, byłbym wdzięczny za komentarz, a nie za natychmiastowe zdanie. Ponadto, jeśli CoffeeScript jest trudny do odczytania, odwiedź coffeescript.org, kliknij „wypróbuj coffeescript” i wklej mój kod, aby zobaczyć skompilowaną wersję, która (mam nadzieję) może mieć większy sens. Dzięki!
źródło
Zakładam, że większość osób, które zadają to pytanie, zna już podstawowe pojęcia, więc nie trzeba o tym rozmawiać. To nakładanie się jest mylące.
Być może będziesz w stanie w pełni korzystać z tych pojęć, ale rozumiesz je razem jako pseudoatomowe amorficzne rozmycie pojęciowe. Brakuje tylko wiedzy, gdzie jest granica między nimi.
Zamiast definiować, czym jest każdy, łatwiej jest podkreślić tylko ich różnice - granicę.
Curry ma miejsce, gdy zdefiniujesz funkcję.
Częściowe zastosowanie następuje po wywołaniu funkcji.
Aplikacja ma funkcję matematyczną do wywoływania funkcji.
Częściowa aplikacja wymaga wywołania funkcji curry i uzyskania funkcji jako typu zwracanego.
źródło
Są tutaj inne świetne odpowiedzi, ale uważam, że ten przykład (według mojego zrozumienia) w Javie może być korzystny dla niektórych osób:
Curry daje więc funkcję jednoparametrową do tworzenia funkcji, przy czym częściowa aplikacja tworzy funkcję otoki, która koduje jeden lub więcej argumentów.
Jeśli chcesz skopiować i wkleić, poniższe ustawienia są bardziej głośne, ale łatwiejsze w obsłudze, ponieważ typy są łagodniejsze:
źródło
Pisząc to, pomyliłem curry i nieświadomość. Są odwrotnymi przekształceniami funkcji. Tak naprawdę nie ma znaczenia, jak to nazywacie, o ile otrzymacie to, co reprezentuje transformacja i jej odwrotność.
Niepocieszanie nie jest zdefiniowane bardzo jasno (a raczej istnieją „sprzeczne” definicje, które oddają ducha idei). Zasadniczo oznacza to przekształcenie funkcji, która przyjmuje wiele argumentów w funkcję, która przyjmuje pojedynczy argument. Na przykład,
Jak zatem zmienić to w funkcję, która wymaga jednego argumentu? Oczywiście oszukujesz!
Zauważ, że plus przyjmuje teraz pojedynczy argument (który składa się z dwóch rzeczy). Wspaniały!
Jaki jest tego sens? Cóż, jeśli masz funkcję, która pobiera dwa argumenty i masz parę argumentów, miło jest wiedzieć, że możesz zastosować tę funkcję do argumentów i nadal uzyskać to, czego oczekujesz. W rzeczywistości instalacja hydrauliczna już istnieje, więc nie musisz robić rzeczy takich jak jawne dopasowywanie wzorców. Wszystko co musisz zrobić to:
Czym jest zastosowanie funkcji częściowej? Jest to inny sposób na przekształcenie funkcji z dwóch argumentów w funkcję z jednym argumentem. Działa to jednak inaczej. Ponownie weźmy (+) jako przykład. Jak możemy przekształcić go w funkcję, która jako argument przyjmuje pojedynczy Int? Oszukujemy!
To funkcja, która dodaje zero do dowolnego Int.
dodaje 1 do dowolnego Int. Itd. W każdym z tych przypadków (+) jest „częściowo stosowany”.
źródło