Pobierz prezentację
Pobieranie prezentacji. Proszę czekać
OpublikowałLechosława Głos Został zmieniony 9 lat temu
1
Haskell
2
Dopasowanie do wzorca Jest to operacja, gdzie pewnie wyrażenie sprawdza się ze wzorcem, w którym może znajdować się jedno lub więcej "wolnych miejsc". W wyniku, o ile nastąpiło dopasowanie otrzymuje się listę wyrażeń, które dopasowały się do wolnych miejsc wzorca. W językach funkcyjnych wykorzystuje się system wzorców symbolicznych.
3
Dopasowanie do wzorca Przykład: Aplikacja, która wypisze „Trafiłeś szczęśliwą liczbę” w przypadku napotkania siódemki, oraz „Liczba nie jest szczęśliwa” w przeciwnym wypadku. Plik szczesliwaLiczba.hs szczesliwaLiczba::(Integral a)=> a-> String szczesliwaLiczba 7 = "Trafiles szczesliwa liczbe." szczesliwaLiczba x = "Liczba nie jest szczesliwa. "
4
Dopasowanie do wzorca Ten sam przykład można zapisać w nieco inny sposób: szczesliwaLiczba n = case n of 7 -> "Trafiles szczesliwa liczbe." _ -> "Liczba nie jest szczeliwa" Lub szczesliwaLiczba n | n == 7 = " Trafiles szczesliwa liczbe. " | otherwise = " Liczba nie jest szczeliwa "
5
Dopasowanie do wzorca W kolejnym przykładzie sprawdzimy czy liczba mieści się w zakresie i wypiszemy ją jako string. Przykład: sayMe :: (Integral a) => a -> String sayMe 1 = "One!" sayMe 2 = "Two!" sayMe 3 = "Three!" sayMe 4 = "Four!" sayMe 5 = "Five!" sayMe x = "Not between 1 and 5"
6
Silnia rekurencyjnie Przypomnienie czym jest silnia: Jest to iloczyn wszystkich liczb naturalnych nie większych niż n. 4! = 1 · 2 · 3 · 4 = 24. Przypomnienie czym jest rekurencja: Odwoływanie się funkcji do samej siebie.
7
Silnia rekurencyjnie Przykład: fac :: Int -> Int fac n | n = 0" | n == 0 = 1 | otherwise = n * fac (n - 1)
8
Silnia rekurencyjnie – drugi sposób Przykład: factorial :: (Integral a) => a -> a factorial 0 = 1 factorial n = n * factorial (n - 1)
9
Silnia rekurencyjnie – drugi sposób Wyjaśnienie działania dla n=3. W pierwszym kroku obliczamy 3 * silnia(2) Silnia(2) to: 2 * silnia(1) Silnia(1) to 1 * Silnia(0) Co w sumie daje: 3 * (2 * (1 * silnia 0)) Z czego otrzymujemy 3 * (2 * (1 * 1)) Z tego wynika, że kolejność jest bardzo istotna!
10
Krotki na przykładzie wektorów Dodanie do siebie dwóch wektorów. Komponenty x muszą być dodane oddzielnie, oraz ich elementy y oddzielnie. addVectors :: (Num a) => (a, a) -> (a, a) -> (a, a) addVectors a b = (fst a + fst b, snd a + snd b) lub addVectors :: (Num a) => (a, a) -> (a, a) -> (a, a) addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)
11
Krotki na przykładzie wektorów A co, jeśli chcielibyśmy użyć trójek? _ oznacza cokolwiek first :: (a, b, c) -> a first (x, _, _) = x second :: (a, b, c) -> b second (_, y, _) = y third :: (a, b, c) -> c third (_, _, z) = z Przykład: ghci > let xs = [(1,3), (4,3), (2,4), (5,3), (5,6), (3,1)] ghci > [a+b | (a,b) <- xs] [4,7,6,8,11,4]
12
Inne przykłady - listy head ' :: [a] -> a head ' [] = error "Can't call head on an empty list, dummy!" head ' (x:_) = x [] – oznacza listę pustą ghci > head ' [4,5,6] 4 ghci > head ' "Hello" 'H'
13
Inne przykłady - listy tell :: (Show a) => [a] -> String tell [] = "The list is empty" tell (x:[]) = "The list has one element: " ++ show x tell (x:y:[]) = "The list has two elements: " ++ show x ++ " and " ++ show y tell (x:y:_) = "This list is long. The first two elements are: " ++ show x ++ " and " ++ show y
14
Przykład z BMI bmiTell :: (RealFloat a) => a -> String bmiTell bmi | bmi <= 18.5 = "You're underweight, you emo, you!" | bmi <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!" | bmi <= 30.0 = "You're fat! Lose some weight, fatty!" | otherwise = "You're a whale, congratulations!„ bmiTell :: (RealFloat a) => a -> a -> String bmiTell weight height | weight / height ^ 2 <= 18.5 = "You're underweight, you emo, you!" | weight / height ^ 2 <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!" | weight / height ^ 2 <= 30.0 = "You're fat! Lose some weight, fatty!" | otherwise = "You're a whale, congratulations!" Let’s see if I’m fat... ghci > bmiTell 85 1.90 "You're supposedly normal. Pffft, I bet you're ugly!"
15
Przykład z WHERE bmiTell :: (RealFloat a) => a -> a -> String bmiTell weight height | bmi <= 18.5 = "You're underweight, you emo, you!" | bmi <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!" | bmi <= 30.0 = "You're fat! Lose some weight, fatty!" | otherwise = "You're a whale, congratulations!" where bmi = weight / height ^ 2 Lub bmiTell :: (RealFloat a) => a -> a -> String bmiTell weight height | bmi <= skinny = "You're underweight, you emo, you!" | bmi <= normal = "You're supposedly normal. Pffft, I bet you're ugly!" | bmi <= fat = "You're fat! Lose some weight, fatty!" | otherwise = "You're a whale, congratulations!" where bmi = weight / height ^ 2 skinny = 18.5 normal = 25.0 fat = 30.0
16
Przykład z LET ghci > let zoot x y z = x * y + z ghci > zoot 3 9 2 29 ghci > let boot x y z = x * y + z in boot 3 4 2 14
17
CASE case expression of pattern -> result pattern -> result...
18
CZĘŚĆ 2 REKURENCJA Żeby zrozumieć rekurencję, musisz zrozumieć rekurencję.
19
Silnia Ćwiczenie -> zaimplementować silnie, była już omawiana.
20
Mnożenie Z pewnością każdy programista, zarówno piszący w językach imperatywnych jak i funkcyjnych, aby pomnożyć dwie liczby a i b napisze po prostu a * b. Mnożenie można jednak zapisać w sposób rekurencyjny. Wykorzystamy do tego definicję podawaną dzieciom w szkole podstawowej. Aby pomnożyć liczbę a razy liczbę b, weź liczbę a i dodaj do siebie b razy. Na przykład 6*4 = 6+6+6+6. Podobnie jak w poprzednim przykładzie, zapiszmy dwa przykłady mnożenia. 6 * 4 = 6 + 6 + 6 + 6 6 * 3 = 6 + 6 + 6
21
Mnożenie – uogólnienie a * b = a + a * (b-1) Oraz przypadek bazowy a * 0 = 0
22
Implementacja Samodzielnie zaimplementuj pomnoz a 0 = 0 pomnoz a b = a + pomnoz a (b-1)
23
Maxiumum maksimum :: [Int] -> Int maksimum [x] = x maksimum (x:xs) | x > maks = x | otherwise = maks where maks = maksimum xs
24
Rekurencja ogonowa Rekurencja ogonowa, zwana też Tail call lub prawostronną jest rodzajem rekurencji, w której ostatnia operacja wykonywana przez funkcję to rekurencyjne wywołanie samej siebie lub zwrócenie końcowego wyniku. Taka funkcja może zostać łatwo zamieniona na iterację, zarówno ręcznie, jak i automatycznie, co redukuje wielkość stosu oraz zwiększa wydajność. Ta technika iteracyjnego wykonywania obliczeń jest powszechna w programowaniu funkcyjnym promującym używanie rekurencji, która w przeciwnym wypadku zajęłaby cały dostępny stos.
25
Rekurencja ogonowa maksimum' :: [Int] -> Int maksimum' (x:xs) = maks xs x where maks [] m = m maks (x:xs) m | x > m = maks xs x | otherwise = maks xs m
Podobne prezentacje
© 2024 SlidePlayer.pl Inc.
All rights reserved.