2009-09-25 13 views
21

Czytam this samouczek na temat Haskella. Określają one funkcji składu jak:Kompozycja funkcji Haskella

(.)      :: (b->c) -> (a->b) -> (a->c) 
f . g     = \ x -> f (g x) 

Brak przykłady zostały dostarczone, które wierzę, że mnie oświecić, co jest zdefiniowane są tutaj.

Czy ktoś może podać prosty przykład (z wyjaśnieniem), w jaki sposób wykorzystuje się skład funkcji?

Odpowiedz

38

Kompozycja funkcji jest sposobem "skomponowania" dwóch funkcji w jedną funkcję. Oto przykład:

Załóżmy, że masz te funkcje:

even :: Int -> Bool 
not :: Bool -> Bool 

i chcesz zdefiniować własną myOdd :: Int -> Bool funkcji za pomocą dwóch wyżej.

Oczywistym sposobem na to jest następująca:

myOdd :: Int -> Bool 
myOdd x = not (even x) 

Ale można to zrobić bardziej zwięźle użyciu złożenie funkcji:

myOdd :: Int -> Bool 
myOdd = not . even 

W myOdd funkcje zachowują się dokładnie tak samo, ale drugi jeden jest tworzony przez "sklejanie" dwóch funkcji razem.

Scenariusz, w którym jest to szczególnie przydatne, polega na usunięciu potrzeby jawnego lambda. Np:

map (\x -> not (even x)) [1..9] 

może być zapisane do:

map (not . even) [1..9] 

Nieco krótsze, mniej miejsca na błędy.

+0

Jak to się dzieje, że nie trzeba pokazywać parametru wejściowego w definicji? Na przykład. dlaczego nie piszesz 'myOdd x = nie. nawet x'? – unclerojelio

+2

@unclerojelio Nazywa się styl bez punktów. Zamiast definiować 'myOdd' pod względem wyniku dla danego argumentu (" Given 'x',' myOdd' zwraca taką samą wartość jak '(not. Even) x'), jest zdefiniowane pod względem tego, co faktycznie is ("' myOdd' to funkcja, która powstaje, gdy 'not' jest złożony z' even' "). – chepner

13

kompozycja z f i g jest funkcją pierwszym stosuje g jej argumentów, następnie f do wartości powrotu g. Następnie zwraca wartość zwracaną f.

Tożsamość ta może być pouczające:

f (g x) = (f . g) x

Jeśli masz Java/C tła, rozważmy następujący przykład:

int f(int x); 
int g(int x); 
int theComposition(int x) { return f(g(x)); } 
+0

+1 za równoważność – outis

4

Z HaskellWiki page on function composition:

desort = (reverse . sort) 

Teraz desort jest funkcja sortująca listę w odwrotnej kolejności. Zasadniczo desort podaje swoje argumenty do sort, a następnie podaje wartość zwracaną z sort do reverse, a następnie zwraca tę wartość. Więc to sortuje, a następnie odwraca posortowaną listę.

7

Ten przykład jest wymyślony, ale załóżmy, że mamy

sqr x = x * x 
inc x = x + 1 

i chcemy napisać funkcję, która oblicza x^2 + 1. można napisać

xSquaredPlusOne = inc . sqr 

(co oznacza

xSquaredPlusOne x = (inc . sqr) x 

co oznacza

xSquaredPlusOne x = inc(sqr x) 

od f = INC i g = SQR).

26

Zabawna notatka. Kompozycja funkcji jest odpowiednikiem sylogizmu w logice:

Wszyscy ludzie są śmiertelni. Sokrates to człowiek. Dlatego Sokrates jest śmiertelny.

sylogizm tworzy dwie istotne konsekwencje w postaci jednej:

(Man => Mortal), (Socrates => Man), therefore (Socrates => Mortal) 

Dlatego ...

(b -> c) -> (a -> b) -> (a -> c) 

..., który jest typem funkcji ..

3

Skład funkcji to sposób połączenia dwóch lub więcej funkcji. Jest często porównywany do rurociągów muszli. Na przykład, w powłoce Unix stylu, można napisać coś podobnego

cat foo.txt | sort -n | less 

ten biegnie cat, karmi swoje wyjście do sort i karmi wyjście od tego, do less.

Ściśle, jest to podobne do operatora Haskell $. Możesz napisać coś w stylu:

sum $ sort $ filter (> 0) $ my_list 

Zauważ, że w przeciwieństwie do przykładu powłoki, odczytuje od prawej do lewej. Zaczynamy od my_list jako danych wejściowych, a następnie uruchamiamy nad nim filter, a następnie je sort, a następnie obliczamy wartość .

Operator składu funkcji, ., robi coś podobnego. Powyższy przykład wytwarza numer o numerze; Poniższy przykład tworzy funkcję:

sum . sort . filter (> 0) 

Zauważ, że w rzeczywistości nie karmić listę do tego. Zamiast tego właśnie stworzyliśmy nową funkcję i możemy podać kilka różnych list do tej funkcji.Na przykład, można nazwać tę funkcję:

my_function = sum . sort . filter (> 0) 

Albo może przekazać go jako argument do innej funkcji:

map (sum . sort . filter (> 0)) my_lists 

Można w zasadzie wykorzystać go w dowolnym miejscu, które można użyć dowolnego innego rodzaju funkcji . To tylko szybki i czytelny sposób powiedzenia "Chcę połączyć te funkcje razem".