Rekurencja Ponieważ w Haskellu nie mamy klasycznych pętli for czy while dlatego w wielu algorytmach musimy używać rekurencji.
Alborytm na n liczbe ciagu Fibonacciego: fib :: Integer -> Integer fib 0 = 0 fib 1 = 1 fib n = fib ( n - 2) +fib ( n - 1) Maximum: maximum' :: ( Ord a) => [a] -> a maximum' [] = error " maximum of empty list " maximum' [x] = x maximum' (x: xs ) (lub = max x ( maximum2 xs ) ) | x > maxTail = x | otherwise = maxTail where maxTail = maximum' xs Algorytm rekurencyjnego szukania maximu zwykle nie polaga na aktualizowaniu zmiennej przechowujacej potencjalny max podczas sprawdzania wszystkich elemntów ciagu. Algorytm maximum w haskellu polega na porównywaniu pierwszego elementu z ciagu z rekurencyjnym wywołaniem funkcji dla pozostałych elemntów. Przykład: [2,5,1] -> 2 ; [5, 1] -> 5 ; [1] -> 1
Replicate replicate' :: ( Num i , Ord i ) => i -> a -> [a] replicate' n x | n <= 0 = [] | otherwise = x:replicate' (n -1) x ( lub | otherwise = [x] ++ replicate‘ (n -1) x-} ) Użylismy tutaj starażnika zamiast wzorca ponieważ sprawdzamy warunek logiczny. Jeżeli n jest mniejsze lub równe zero zwracamy pustą listę. Przykład: replicate’ 3 5 -> [5, 5, 5] Take take ’ :: ( Num i , Ord i ) => i -> [a] -> [a] take ’ n _ take ’ _ [] = [] take ’ n (x: xs ) = x : take ’ (n -1) xs Przykład: take 3 [5,4,3,2,1] -> [5] : take 2 [4,3,2,1] -> [5,4] : take 1 [3,2,1] -> [5,4,3] : take 0 [2,1] -> [5,4,3]: [] -> [5,4,3]
Reverse Repeat reverse' :: [a] -> [a] reverse' [] = [] reverse' (x: xs ) = reverse' xs ++ [ x] Revarse polega na przepisywaniu pierwszego elmentu na koniec listy aż do przepisania wszystkich. Przykład: reverse [1,2,3] -> reverse [2,3] ++ [1] |reverse[3] ++[2] |[]++[3] Repeat repeat ’ :: a -> [a] repeat ’ x = x: repeat ’ x W Haskelu jeżeli w funkcji rekurencyjnej nie określimy warunku końca to w pwenych przypadkach funkcja taka da wynik nieskończony w powyższej funkcji wynik jest nieskończony i bedzie drukowany tak długo aż użytkownik tego nie przerwie. Mozemy zauważyć ze funkcje rekurencyjne w haskelu powstaja według pewnego schematu : Obsługujemy sytułacje wyjatkowe Obsługujemy główną właściwość algorytmu Funkcja wykonuje operacje na części danych a dla pozostałych wykonywane jest kolejne zagłębienie
Zip Elem zip ’ :: [a] -> [b] -> [( a ,b )] zip ’ _ [] = [] zip ’ (x: xs ) (y: ys ) = (x ,y ): zip ’ xs ys Przykład: zip [1,2,3] [’a’,’b’] -> [(1,’a’),(2,’b’)] Na początku alhotytm spawdza czy jedna z list jest pusta, jeżeli tak to zwarca pustą listę. W przeciwnym wypadku łączy głowy obu list w krotkę i dodaje do tablicy a dla ogonów uruchamia kolejne zagłębienie. Elem elem ’ :: ( Eq a) => a -> [a] -> Bool elem ’ a [] = False elem ’ a (x: xs ) | a == x = True | otherwise = a ‘ elem ’‘ xs (| otherwise = elem a xs) Przykład: elem 1 [1,2,3] -> True
QuickSort quicksort :: ( Ord a) => [a ] -> [a ] quicksort (x: xs ) = let smallerSorted = quicksort [a | a <- xs , a <= x] biggerSorted = quicksort [a | a <- xs , a > x] in smallerSorted ++ [x] ++ biggerSorted Przykład: quicksort [5,1,9,4,6,7,3] -> quicksort [1,4,3] ++ [5] ++ quicksort [9,6,7] quicksort [1,4,3] -> quicksort [] ++ [1] ++ quicksort [4, 3 ] quicksort [9,6,7] -> quicksort [6,7] ++ [9] ++ quicksort [] quicksort [4,3] -> quicksort [3] ++ [4] ++ quicksort [] quicksort [6,7] -> quicksort [] ++ [6] ++ quicksort [7]