DEFINICJA I ZASTOSOWANIE W JĘZYKU HASKELL Rekursja DEFINICJA I ZASTOSOWANIE W JĘZYKU HASKELL
Rekursja (Rekurencja) Rekurencja jest to termin który występuje zarówno w matematyce jak i w informatyce. Rekursja oznacza iż w funkcja wywołuje samą siebie w celu rozwiązania pewnego problemu. Zazwyczaj zadania rozwiązywane techniką rekurencyjną są wolniejsze niż ich iteracyjne odpowiedniki, natomiast w niektórych przypadkach zapis rozwiązania rekurencyjnego jest dużo bardziej prosty i zrozumiały.
Rekurencja w matematyce Przykład matematyczny wykorzystania rekurencji to obliczanie kolejnych wyrazów Ciągu Fibonacci’ego: Dla przykładu, obliczenie fib(4) wygląda następująco:
Rekurencja w Haskell Rekurencja jest niejako wymuszona w języku Haskell z tego względu iż nie jest możliwa zmiana wartości zmiennych. Co za tym idzie niemożliwe jest użycie pętli – instrukcje takie nie istnieją w języku Haskell. Przykład rozwiązania problemu wyznaczania n-tego wyrazu Ciągu Fibonacci’ego:
Funkcja Maximum Zobaczmy jak wygląda implementacja funkcji MAXIMUM w języku Haskell:
Opis funkcji Pierwszy warunek sprawdza czy lista nie jest pusta, jeżeli tak jest zwraca błąd: „maximum of empty list”; Drugi warunek sprawdza czy podana lista jest jednoelementowa, jeżeli jest to zwraca właśnie ten element; Jeżeli poprzednie warunki nie zostały zrealizowane z podanej listy tworzone są dwie: head i tail. Używamy funkcji where w celu zdefiniowania zmiennej maxTail jako maksimum „ogona”, następnie sprawdzamy czy „głowa” jest większa od maxTail. Jeśli tak – zwracamy głowę jako wynik, jeśli nie zwracamy maximum reszty listy.
Przykład użycia funkcji maximum Przykładowa tablica: [2, 1, 5] Dzielimy tablicę na head: [2] i tail: [1, 5], następnie wywołujemy funkcję maximum dla tail. Tail: [1, 5] jest dzielony na head: [1] i tail: [5], co oznacza spełniony jeden z warunków końca rekurencji. Porównujemy 1 i 5, zwrócone zostaje 5. Wracamy „na wierzch” rekurencji i porównujemy 5 i 2. Zwrócone zostaje 5 jako największa wartość tablicy.
Funkcja replicate Kolejna rekurencyjna funkcja której zadaniem jest powtórzenie drugiego argumentu tyle razy ile podane jest w argumencie pierwszym. Przykładowe wywołanie funkcji: replicate 4 6, wynikiem będzie lista składająca się z czterech szóstek: [6, 6, 6, 6]
Funkcja take Funkcja ta pobiera liczbę elementów (podaną jako pierwszy jej argument) tablicy (podaną jako drugi jej argument) i zwraca ją na ekran. W zależności od tego jakie wartości przyjmie funkcja take zwracane są odpowiednie wartości zapisane w 2, 4 lub 5 linii.
Funkcja reverse Funkcja przyjmuje listę elementów oraz zwraca tą listę w odwróconej kolejności.
Funkcja quicksort Dzięki tej funkcji możliwe jest posortowanie elementów wielu typów. Dzieli ona rekurencyjnie problem na mniejsze podproblemy co najlepiej prezentuje grafika z kolejnego slajdu. A oto kod:
Grafika ilustrująca działanie algorytmu
Podsumowanie W dotychczasowych przykładach zauważyć można pewną zależność która dotyczy rekurencyjnych algorytmów. W pierwszych liniach rozważamy przypadki końcowe i szczególne dla danych struktur czy typowych sytuacji. Np. dla list będzie to sytuacja kiedy lista będzie pusta lub gdy w drzewie pozostanie wierzchołek który nie ma dzieci. Dopiero w ostatniej linii zapisane jest wywołanie funkcji przez siebie samą.