Haskell Dopasowanie do wzorca Jest to operacja gdzie

  • Slides: 25
Download presentation
Haskell

Haskell

Dopasowanie do wzorca Jest to operacja, gdzie pewnie wyrażenie sprawdza się ze wzorcem, w

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.

Dopasowanie do wzorca Przykład: Aplikacja, która wypisze „Trafiłeś szczęśliwą liczbę” w przypadku napotkania siódemki,

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 szczesliwa. Liczba. hs szczesliwa. Liczba: : (Integral a)=> a-> String szczesliwa. Liczba 7 = "Trafiles szczesliwa liczbe. " szczesliwa. Liczba x = "Liczba nie jest szczesliwa. "

Dopasowanie do wzorca Ten sam przykład można zapisać w nieco inny sposób: szczesliwa. Liczba

Dopasowanie do wzorca Ten sam przykład można zapisać w nieco inny sposób: szczesliwa. Liczba n = case n of 7 -> "Trafiles szczesliwa liczbe. " _ -> "Liczba nie jest szczeliwa" Lub szczesliwa. Liczba n | n == 7 = " Trafiles szczesliwa liczbe. " | otherwise = " Liczba nie jest szczeliwa "

Dopasowanie do wzorca W kolejnym przykładzie sprawdzimy czy liczba mieści się w zakresie <1;

Dopasowanie do wzorca W kolejnym przykładzie sprawdzimy czy liczba mieści się w zakresie <1; 5> i wypiszemy ją jako string. Przykład: say. Me : : (Integral a) => a -> String say. Me 1 = "One!" say. Me 2 = "Two!" say. Me 3 = "Three!" say. Me 4 = "Four!" say. Me 5 = "Five!" say. Me x = "Not between 1 and 5"

Silnia rekurencyjnie Przypomnienie czym jest silnia: Jest to iloczyn wszystkich liczb naturalnych nie większych

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.

Silnia rekurencyjnie Przykład: fac : : Int -> Int fac n | n <

Silnia rekurencyjnie Przykład: fac : : Int -> Int fac n | n < 0 = error "n musi byc >= 0" | n == 0 = 1 | otherwise = n * fac (n - 1)

Silnia rekurencyjnie – drugi sposób Przykład: factorial : : (Integral a) => a ->

Silnia rekurencyjnie – drugi sposób Przykład: factorial : : (Integral a) => a -> a factorial 0 = 1 factorial n = n * factorial (n - 1)

Silnia rekurencyjnie – drugi sposób Wyjaśnienie działania dla n=3. W pierwszym kroku obliczamy 3

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!

Krotki na przykładzie wektorów • Dodanie do siebie dwóch wektorów. • Komponenty x muszą

Krotki na przykładzie wektorów • Dodanie do siebie dwóch wektorów. • Komponenty x muszą być dodane oddzielnie, oraz ich elementy y oddzielnie. add. Vectors : : (Num a) => (a, a) -> (a, a) add. Vectors a b = (fst a + fst b, snd a + snd b) lub add. Vectors : : (Num a) => (a, a) -> (a, a) add. Vectors (x 1, y 1) (x 2, y 2) = (x 1 + x 2, y 1 + y 2)

Krotki na przykładzie wektorów A co, jeśli chcielibyśmy użyć trójek? _ oznacza cokolwiek first

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]

Inne przykłady - listy head ' : : [a] -> a head ' []

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'

Inne przykłady - listy tell : : (Show a) => [a] -> String tell

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

Przykład z BMI bmi. Tell : : (Real. Float a) => a -> String

Przykład z BMI bmi. Tell : : (Real. Float a) => a -> String bmi. Tell 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!„ bmi. Tell : : (Real. Float a) => a -> String bmi. Tell 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 > bmi. Tell 85 1. 90 "You're supposedly normal. Pffft , I bet you're ugly!"

Przykład z WHERE bmi. Tell : : (Real. Float a) => a -> String

Przykład z WHERE bmi. Tell : : (Real. Float a) => a -> String bmi. Tell 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 • bmi. Tell : : (Real. Float a) => a -> String • bmi. Tell 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

Przykład z LET ghci > let zoot x y z = x * y

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

CASE • case expression of pattern -> result • . . .

CASE • case expression of pattern -> result • . . .

CZĘŚĆ 2 REKURENCJA Żeby zrozumieć rekurencję, musisz zrozumieć rekurencję.

CZĘŚĆ 2 REKURENCJA Żeby zrozumieć rekurencję, musisz zrozumieć rekurencję.

Silnia • Ćwiczenie -> zaimplementować silnie, była już omawiana.

Silnia • Ćwiczenie -> zaimplementować silnie, była już omawiana.

Mnożenie Z pewnością każdy programista, zarówno piszący w językach imperatywnych jak i funkcyjnych, aby

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

Mnożenie – uogólnienie a * b = a + a * (b-1) Oraz przypadek

Mnożenie – uogólnienie a * b = a + a * (b-1) Oraz przypadek bazowy a*0=0

Implementacja • Samodzielnie zaimplementuj • pomnoz a 0 = 0 • pomnoz a b

Implementacja • Samodzielnie zaimplementuj • pomnoz a 0 = 0 • pomnoz a b = a + pomnoz a (b-1)

Maxiumum maksimum : : [Int] -> Int maksimum [x] = x maksimum (x: xs)

Maxiumum maksimum : : [Int] -> Int maksimum [x] = x maksimum (x: xs) | x > maks = x | otherwise = maks where maks = maksimum xs

Rekurencja ogonowa, zwana też Tail call lub prawostronną jest rodzajem rekurencji, w której ostatnia

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.

Rekurencja ogonowa maksimum' : : [Int] -> Int maksimum' (x: xs) = maks xs

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