Ëåêöèÿ 6. Ðåêóðñèâíûå ôóíêöèè â Haskell Ïåðåæîãèí À.Ñ. 8 îêòÿáðÿ 2012 ã. 1/10 Ðåêóðñèâíûå ôóíêöèè. Ââåäåíèå Ìíîãèå ôóíêöèè â Haskell îïðåäåëÿþòñÿ â òåðìèíàõ äðóãèõ ôóíêöèé.  ïðèìåðå ôóíêöèÿ âû÷èñëåíèÿ ôàêòîðèàëà ïðåäñòàâëÿåòñÿ ÷åðåç ôóíêöèþ âû÷èñëåíèÿ ïðîèçâåäåíèÿ ÷èñåë èç ñïèñêà îò 1 äî n. factorial :: Int -> Int factorial n = product [1..n] Âûðàæåíèå âû÷èñëÿåòñÿ ïî øàãàì = = = = factorial 4 product [1..4] product [1,2,3,4] 1*2*3*4 24 2/10 Ðåêóðñèâíûå ôóíêöèè  Haskell ôóíêöèè ìîãóò áûòü îïðåäåëåíû â òåðìèíàõ ñàìèõ ñåáÿ. Òàêèå ôóíêöèè íàçûâàþòñÿ ðåêóðñèâíûå. factorial 0 = 1 factorial (n+1) = (n+1)*factorial n = = = = = = = factorial 3 3 * factorial 2 3 * (2 * factorial 1) 3 * (2 * (1 *(factorial 0))) 3 * (2 * (1 *1)) 3 * (2 * 1) 3 * 2 6 3/10 Ðåêóðñèâíûå ôóíêöèè Çàìå÷àíèÿ: factorial 0 = 1 ÿâëÿåòñÿ áàçîé ðåêóðñèè, òàê êàê 1 íåéòðàëüíûé ýëåìåíò äëÿ óìíîæåíèÿ ðåêóðñèâíîå îïðåäåëåíèå ôóíêöèè ôàêòîðèàëà ïðè îòðèöàòåëüíûõ öåëûõ ÷èñëàõ äàåò ðàñõîäèìîñòü è ïåðåïîëíåíèå ñòåêà Óäîáñòâî èñïîëüçîâàíèÿ ðåêóðñèè íåêîòîðûå ôóíêöèè áîëåå êîìïàêòíî îáúÿâëÿþòñÿ â òåðìèíàõ ðåêóðñèâíûõ ôóíêöèé ñâîéñòâà ðåêóðñèâíûõ ôóíêöèé äîêàçûâàþòñÿ ñ ïîìîùüþ ìåòîäà ìàòåìàòè÷åñêîé èíäóêöèè 4/10 Ðåêóðñèÿ ñïèñêîâ Ðåêóðñèÿ èñïîëüçóåòñÿ íå òîëüêî äëÿ ÷èñåë, íî òàê æå ïðèìåíÿåòñÿ äëÿ ñïèñêîâ product :: [Int] -> Int product [] = 1 product (n:ns) = n * product ns Ôóíêöèÿ product ïîäñòàâëÿåò âìåñòî ïóñòîãî ñïèñêà åäèíèöó è ïðîèçâîäèò ïåðåìíîæåíèå ãîëîâû íà ïðîèçâåäåíèå ýëåìåíòîâ õâîñòà. = = = = = product [2,3,4] 2 * product [3,4] 2 * ( 3 * product [4]) 2 * ( 3 * ( 4 * product []))) 2 * ( 3 * ( 4 * 1))) 24 5/10 Ðåêóðñèÿ ñïèñêîâ Ðåêóðñèÿ èñïîëüçóåòñÿ íå òîëüêî äëÿ ÷èñåë, íî òàê æå ïðèìåíÿåòñÿ äëÿ ñïèñêîâ product :: [Int] -> Int product [] = 1 product (n:ns) = n * product ns Ôóíêöèÿ product ïîäñòàâëÿåò âìåñòî ïóñòîãî ñïèñêà åäèíèöó è ïðîèçâîäèò ïåðåìíîæåíèå ãîëîâû íà ïðîèçâåäåíèå ýëåìåíòîâ õâîñòà. = = = = = product [2,3,4] 2 * product [3,4] 2 * ( 3 * product [4]) 2 * ( 3 * ( 4 * product []))) 2 * ( 3 * ( 4 * 1))) 24 6/10 Ðåêóðñèÿ ñïèñêîâ Èñïîëüçóÿ ïîäîáíóþ ñõåìó ðåêóðñèè, ìîæíî îïðåäåëèòü ôóíêöèþ äëèíû ñïèñêà length :: [a] -> Int length [] = 0 length (_:xs) = 1 + length xs Ïðèìåð. Ôóíêöèÿ îáðàùåíèÿ ïîðÿäêà â ñïèñêå reverse :: [a] -> [a] reverse [] = [] reverse (x:xs) = reverse xs ++ [x] 7/10 Ðåêóðñèÿ â ñëó÷àå íåñêîëüêèõ àðãóìåíòîâ Ôóíêöèè íåñêîëüêèõ àðãóìåíòîâ ìîãóò èñïîëüçîâàòü ðåêóðñèâíîå îáúÿâëåíèå. Ïðèìåð. Ôóíêöèÿ zipping zip :: zip [] _ = zip _ [] = zip (x:xs) (y:ys) = [a] -> [b] -> [(a,b)] [] [] (x,y) : zip xs ys Ïðèìåð. Ôóíêöèÿ drop drop :: drop 0 xs = drop (n+1) [] = drop (n+1) (_:xs) = Int -> [a] -> [a] xs [] drop n xs Ïðèìåð. Ôóíêöèÿ (++) ñîåäèíåíèÿ äâóõ ñïèñêîâ drop :: drop 0 xs = drop (n+1) [] = drop (n+1) (_:xs) = Int -> [a] -> [a] xs [] drop n xs 8/10 Àëãîðèòì áûñòðîé ñîðòèðîâêè Àëãîðèòì áûñòðîé ñîðòèðîâêè ñïèñêà öåëûõ ÷èñåë ìîæåò áûòü âûïîëíåí ñ ïîìîùüþ äâóõ ïðàâèë: Ïóñòîé ñïèñîê îòñîðòèðîâàí Ñïèñîê ñ ýëåìåíòàìè: ñîðòèðóåì ýëåìåíòû õâîñòà, êîòîðûå ìåíüøå ãîëîâû, è ñîðòèðóåì ýëåìåíòû õâîñòà, êîòîðûå áîëüøå ãîëîâû. Äîáàâëÿåì ðåçóëüòèðóþùèå ñïèñêè ñ îäíîé è äðóãîé ñòîðîíû îò ãîëîâû. qsort :: [Int] -> [Int] qsort [] = [] qsort (x:xs) = qsort smaller ++ [x] ++ qsort larger where smaller = [a | a <- xs, a <= x] larger = [b | b <- xs, b > x] 9/10 Êîíòðîëüíûå çàäàíèÿ Îïðåäåëèòü ôóíêöèè Ëîãè÷åñêîå and and :: [Bool] -> Bool Ëîãè÷åñêîå or or :: [Bool] -> Bool Âûáîð n-ýëåìåíòà èç ñïèñêà (!!) :: [a] -> Int -> Bool Ôóíêöèÿ ïðèíàäëåæíîñòè ýëåìåíòà ñïèñêó elem :: Eq a => a -> [a] -> Bool Ðåêóðñèâíàÿ ôóíêöèÿ msort :: [Int] -> [Int] Ñïèñîê ñîðòèðîâàí, åñëè äëèíà <= 1. Îñòàëüíûå ñïèñêè ñîðòèðóþòñÿ êàê 2 ÷àñòè è îáúåäèíÿþòñÿ â ðåçóëüòèðóþùèé ñïèñîê. 10/10