Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na...

31
Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska, Poznań 2020

Transcript of Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na...

Page 1: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Programowanie funkcyjnew języku Haskell

λStanisław Wasik

Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska, Poznań 2020

Page 2: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Rachunek lambda ● Model obliczeniowy (podstawa języka programowania):

○ Alonzo Church, 1930 → rachunek lambda → prog. funkcyjne (Haskell, OCaml, F#, Erlang, Scala)○ Alan Turing, 1936 → maszyna Turinga → prog. imperatywne (C/C++, C#, Python, Java)

● “Najmniejszy uniwersalny język programowania”:○ zmienna x○ abstrakcja λx.x+1○ aplikacja (λx.x+1)y

● Bazuje na konstruowaniu wyrażeń oraz poddawaniu ich redukcji.● Funkcje nie mają nazw i przyjmują zawsze tylko jeden argument.● Równoważny z maszyną Turinga pod tym względem,

○ że wszystkie algorytmy przedstawione na maszynie Turinga mogą być także zapisane w rachunku lambda oraz na odwrót.

Page 3: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Podstawowe zasady FP● Programowanie deklaratywne → co osiągnąć, nie jak to zrobić.

○ Brak instrukcji sterujących (for, while, switch). ○ Program oparty na rekurencji.

● Zmienne deklaratywne → brak zmiennego stanu.○ Zmienna jako skrót do wartości (nie do miejsca w pamięci):

■ x = 5■ x = 7 -- błąd: próba przypisania wartości 7 do wartości 5■ 5 = 7

● Do obliczenia wyniku używa się tylko argumentów funkcji i globalnych stałych:○ Czysta funkcja (funkcja matematyczna) → łatwiejsze testowanie, łatwiejsze prog. współbieżne.

● Ewaluacja wrażeń zamiast wykonywania instrukcji.○ Programista dostarcza definicje funkcji, nie definiuje jednak kolejności ich wartościowania.○ System wykonawczy wartościuje wybrane funkcje w celu uzyskania wyniku wyrażenia nadrzędnego.○ Nie jest istotne w jakim momencie maszyna dokona wartościowania funkcji (vide czyste funkcje).

Page 4: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Podstawowe zasady FP (2)● Funkcja jako element pierwszej kategorii ( jak obiekt w OOP).

○ Funkcja jest tak samo dobrą wartością jak liczba → można ją np. przypisać do zmiennej:■ uwaga dot. języka Haskell: funkcji używamy bez nawiasów → sqrt 25■ wyrażenie lambda: succ = \x -> x+1 (λx.x+1) succ 12 → 13

■ if condition then log10 15 else log2 15

■ (if condition then log10 else log2) 15

■ funkcja jako argument innej funkcji, tzw. funkcji wyższego rzędu (np. map succ [1,2,3])■ kompozycja funkcji - łącznie funkcji w większe funkcje■ f( g( h(x) ) ) = (f ∘ g ∘ h)(x) ■ (f . g . h) x

○ Spostrzeżenie:■ najważniejszy element w FP: funkcja → sposób przetwarzania danych,■ najważniejszy element w OOP: obiekt → sposób przechowywania danych.

Page 5: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Podstawowe zasady FP (3)● W przypadku programów imperatywnych zakłada się, że wykonanie instrukcji w podanym

przez programistę porządku jest kluczowe do osiągnięcia wyniku.○ Stąd mówimy, że definiujemy strumień sterowania.

● Program funkcyjny jest złożeniem wielu funkcji, programista łączy kolejne bloki przetwarzające dane.○ Wynik jednej funkcji staje się argumentem innej.○ Stąd mówimy, że definiujemy strumień danych, które podlegają przekształceniom.

● Luźna zasada:○ Język funkcyjny stosujemy, gdy dane o małej różnorodności podlegają wielu przekształceniom.○ Język imperatywny stosujemy, gdy wykonujemy mało operacji na różnorodnym zbiorze danych.

● Ciekawostka:○ Klasa w języku Haskell agreguje funkcje (vide język funkcyjny), nie zaś zmienne.○ Instancją klasy jest typ danych, który implementuje zdefiniowane w danej klasie funkcje.

Page 6: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Przykładowe funkcjefib :: Int -> Int

fib 0 = 0

fib 1 = 1

fib n = fib (n-1) + fib (n-2)

add :: Int -> Int -> Int

add a b = a + b

last :: [Int] -> Int

last [h] = h -- [h] jest równoważne z [H]last (h:t) = last t -- (h:t) jest równoważne z [H|T] -- zwyczajowo w języku Haskell zamiast (h:t) używamy oznaczenia (x:xs)

Page 7: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

● Jedna z największych zalet programowania deklaratywnego.● Pozwala na przejrzysty wybór sposobu prowadzenia obliczeń w zależności od wartości

argumentów funkcji.○ System wykonawczy przegląda kolejne deklaracje danej funkcji i wybiera pierwszą pasującą.○ Deklaracja funkcji jest uznana za pasującą, gdy podane wartości argumentów zgadzają się z tymi

zapisanymi w deklaracji lub gdy dla podanego argumentu w deklaracji występuje wolna zmienna.○ factorial 0 = 1

○ factorial n = n * factorial (n-1)

● Umożliwia dekonstrukcję wartości złożonych:○ Inaczej: umożliwia związanie poszczególnych wartości składowych wartości złożonej ze zmiennymi.○ [x,y,z] = [1,2,3] → x = 1 y = 2 z = 3

○ (h:t) = [1,2,3] → h = 1 t = [2,3] ponieważ 1:[2,3] → [1,2,3]

○ (a:b:c) = [1,2,3] → a = 1 b = 2 c = [3]

● Zaleta: w programach deklaratywnych nie ma potrzeby używania wyrażeń if.

Dopasowanie do wzorca

Page 8: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Implikacja

(==>) :: Bool -> Bool -> Bool

True ==> True = True

True ==> False = False

False ==> True = True

False ==> False = True

Dopasowanie do wzorca (2)

(==>) :: Bool -> Bool -> Bool

True ==> False = False

_ ==> _ = True

head :: [Int] -> Int

head (h:_) = h

Page 9: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

● Jest mechanizmem wyznaczania wartości dopiero w momencie, gdy wartość ta jest wymagana do kontynuacji obliczeń.

● By uzyskać wynik funkcji dokonywana jest analiza wyrażenia. Następnie wartościowane są tylko te funkcje, których wyniki są konieczne do obliczenia wartości końcowej.

nthEvenNatural n = evenNatural !! (n-1)

where infinite = [1..]

evenNatural = [2,4..]

● Mechanizm ten kontroluje obliczenia w taki sposób, by wartość danego wyrażenia była obliczona tylko i wyłącznie raz.

● Pozwala na tworzenie nieskończonych struktur danych.○ Zmienna przechowująca taką strukturę zawiera funkcję (tzw. obietnicę obliczenia wartości), na

podstawie której możliwe jest wyznaczenie zawartości struktury.

Leniwe wartościowanie

Page 10: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Inna, iteracyjna definicja ciągu Fibonacciego:

fibs :: [Int]

fibs = 0 : 1 : zipWith (+) (tail fibs) fibs

zipWith (++) [“a”, “b”, “c”] [“1”, “2”, “3”] → [“a1”, “b2”, “c3”]

>>> fibs !! 5 -- (!!) to operator indeksowania listy

Leniwe wartościowanie (2)

Page 11: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Inna, iteracyjna definicja ciągu Fibonacciego:

fibs :: [Int]

fibs = 0 : 1 : zipWith (+) (tail fibs) fibs

zipWith (++) [“a”, “b”, “c”] [“1”, “2”, “3”] → [“a1”, “b2”, “c3”]

>>> fibs !! 5 -- (!!) to operator indeksowania listy

fibs = [0, 1,···]

Leniwe wartościowanie (2)

Page 12: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Inna, iteracyjna definicja ciągu Fibonacciego:

fibs :: [Int]

fibs = 0 : 1 : zipWith (+) (tail fibs) fibs

zipWith (++) [“a”, “b”, “c”] [“1”, “2”, “3”] → [“a1”, “b2”, “c3”]

>>> fibs !! 5 -- (!!) to operator indeksowania listy

[1,···] ← tail fibs

fibs = [0, 1, + ← fibs

[0, 1,···] ← fibs

Leniwe wartościowanie (2)

Page 13: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Inna, iteracyjna definicja ciągu Fibonacciego:

fibs :: [Int]

fibs = 0 : 1 : zipWith (+) (tail fibs) fibs

zipWith (++) [“a”, “b”, “c”] [“1”, “2”, “3”] → [“a1”, “b2”, “c3”]

>>> fibs !! 5 -- (!!) to operator indeksowania listy

[1, 1,···] ← tail fibs

fibs = [0, 1, 1, ← fibs

[0, 1, 1,···] ← fibs

Leniwe wartościowanie (2)

Page 14: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Inna, iteracyjna definicja ciągu Fibonacciego:

fibs :: [Int]

fibs = 0 : 1 : zipWith (+) (tail fibs) fibs

zipWith (++) [“a”, “b”, “c”] [“1”, “2”, “3”] → [“a1”, “b2”, “c3”]

>>> fibs !! 5 -- (!!) to operator indeksowania listy

[1, 1,···] ← tail fibs

fibs = [0, 1, 1, + ← fibs

[0, 1, 1,···] ← fibs

Leniwe wartościowanie (2)

Page 15: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Inna, iteracyjna definicja ciągu Fibonacciego:

fibs :: [Int]

fibs = 0 : 1 : zipWith (+) (tail fibs) fibs

zipWith (++) [“a”, “b”, “c”] [“1”, “2”, “3”] → [“a1”, “b2”, “c3”]

>>> fibs !! 5 -- (!!) to operator indeksowania listy

[1, 1, 2,···] ← tail fibs

fibs = [0, 1, 1, 2, ← fibs

[0, 1, 1, 2,···] ← fibs

Leniwe wartościowanie (2)

Page 16: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Inna, iteracyjna definicja ciągu Fibonacciego:

fibs :: [Int]

fibs = 0 : 1 : zipWith (+) (tail fibs) fibs

zipWith (++) [“a”, “b”, “c”] [“1”, “2”, “3”] → [“a1”, “b2”, “c3”]

>>> fibs !! 5 -- (!!) to operator indeksowania listy

[1, 1, 2,···] ← tail fibs

fibs = [0, 1, 1, 2, + ← fibs

[0, 1, 1, 2,···] ← fibs

Leniwe wartościowanie (2)

Page 17: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Inna, iteracyjna definicja ciągu Fibonacciego:

fibs :: [Int]

fibs = 0 : 1 : zipWith (+) (tail fibs) fibs

zipWith (++) [“a”, “b”, “c”] [“1”, “2”, “3”] → [“a1”, “b2”, “c3”]

>>> fibs !! 5 -- (!!) to operator indeksowania listy

[1, 1, 2, 3,···] ← tail fibs

fibs = [0, 1, 1, 2, 3, ← fibs

[0, 1, 1, 2, 3,···] ← fibs

Leniwe wartościowanie (2)

Page 18: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Inna, iteracyjna definicja ciągu Fibonacciego:

fibs :: [Int]

fibs = 0 : 1 : zipWith (+) (tail fibs) fibs

zipWith (++) [“a”, “b”, “c”] [“1”, “2”, “3”] → [“a1”, “b2”, “c3”]

>>> fibs !! 5 -- (!!) to operator indeksowania listy

[1, 1, 2, 3,···] ← tail fibs

fibs = [0, 1, 1, 2, 3, + ← fibs

[0, 1, 1, 2, 3,···] ← fibs

Leniwe wartościowanie (2)

Page 19: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Inna, iteracyjna definicja ciągu Fibonacciego:

fibs :: [Int]

fibs = 0 : 1 : zipWith (+) (tail fibs) fibs

zipWith (++) [“a”, “b”, “c”] [“1”, “2”, “3”] → [“a1”, “b2”, “c3”]

>>> fibs !! 5 -- (!!) to operator indeksowania listy

[1, 1, 2, 3, 5,···] ← tail fibs

fibs = [0, 1, 1, 2, 3, 5, ← fibs

[0, 1, 1, 2, 3, 5,···] ← fibs

Leniwe wartościowanie (2)

Page 20: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Inna, iteracyjna definicja ciągu Fibonacciego:

fibs :: [Int]

fibs = 0 : 1 : zipWith (+) (tail fibs) fibs

zipWith (++) [“a”, “b”, “c”] [“1”, “2”, “3”] → [“a1”, “b2”, “c3”]

>>> fibs !! 5 -- (!!) to operator indeksowania listy

[1, 1, 2, 3, 5,···] ← tail fibs

fibs = [0, 1, 1, 2, 3, 5, ← fibs

[0, 1, 1, 2, 3, 5,···] ← fibs

Leniwe wartościowanie (2)

Page 21: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Inna, iteracyjna definicja ciągu Fibonacciego:

fibs :: [Int]

fibs = 0 : 1 : zipWith (+) (tail fibs) fibs

zipWith (++) [“a”, “b”, “c”] [“1”, “2”, “3”] → [“a1”, “b2”, “c3”]

>>> fibs !! 5 -- (!!) to operator indeksowania listy

[1, 1, 2, 3, 5,···] ← tail fibs

fibs = [0, 1, 1, 2, 3, 5,···] ← fibs

[0, 1, 1, 2, 3, 5,···] ← fibs

Leniwe wartościowanie (2)

Page 22: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Inna, iteracyjna definicja ciągu Fibonacciego:

fibs :: [Int]

fibs = 0 : 1 : zipWith (+) (tail fibs) fibs

zipWith (++) [“a”, “b”, “c”] [“1”, “2”, “3”] → [“a1”, “b2”, “c3”]

>>> fibs !! 5 -- (!!) to operator indeksowania listy

fibs = [0, 1, 1, 2, 3, 5,···]

Leniwe wartościowanie (2)

Page 23: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Inna, iteracyjna definicja ciągu Fibonacciego:

fibs :: [Int]

fibs = 0 : 1 : zipWith (+) (tail fibs) fibs

zipWith (++) [“a”, “b”, “c”] [“1”, “2”, “3”] → [“a1”, “b2”, “c3”]

>>> fibs !! 5 -- (!!) to operator indeksowania listy5

fibs = [0, 1, 1, 2, 3, 5,···]

Leniwe wartościowanie (2)

Page 24: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Currying● Funkcje przyjmują zawsze tylko jeden argument.● Currying to proces przekształcania funkcji wieloargumentowej w złożenie funkcji

jednoargumentowych, w którym każda z funkcji przyjmuje jeden argument oraz zwraca funkcję przyjmującą kolejny argument.

● Pochodzi od nazwiska Haskella Curry’ego.

modExp :: Int -> Int -> Int -> Int

modExp a b c = a ^ b `mod` c

modExp :: Int -> Int -> Int -> Int

modExp = \a b c -> a ^ b `mod` c

modExp :: Int -> Int -> Int -> Int

modExp = \a -> \b -> \c -> a ^ b `mod` c

Page 25: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Currying (2)modExp :: Int -> (Int -> (Int -> Int))

modExp = \a -> (\b -> (\c -> a ^ b `mod` c))

x = modExp 12 y = modExp 12 4

map (\x -> max 15 x) [5,10,15,20,25] ⟺ map (max 15) [5,10,15,20,25]

→ [15,15,15,20,25]

toLower :: String -> String

toLower string = map lower string ⟺ toLower = map lower

Currying w Pythonie:curried_mod_exp = lambda a: lambda b: lambda c: a ** b % c

>>> curried_mod_exp(4,3,6)

Page 26: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Currying (2)modExp :: Int -> (Int -> (Int -> Int))

modExp = \a -> (\b -> (\c -> a ^ b `mod` c))

x = modExp 12 y = modExp 12 4

map (\x -> max 15 x) [5,10,15,20,25] ⟺ map (max 15) [5,10,15,20,25]

→ [15,15,15,20,25]

toLower :: String -> String

toLower string = map lower string ⟺ toLower = map lower

Currying w Pythonie:curried_mod_exp = lambda a: lambda b: lambda c: a ** b % c

>>> curried_mod_exp(4,3,6) curried_mod_exp(4)(3)(6)

Page 27: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Monady● Monada (ang. monad) jest rodzajem kontenera przechowującego wartości lub funkcje. ● Pozwala na budowanie sekwencji obliczeń poprzez łączenie bloków (funkcji).

○ Łączenie przebiega z zastosowaniem odpowiedniej strategii.● Każdy monadyczny typ danych definiuje sposób łączenia bloków ze sobą zwalniając

programistę z konieczności ręcznej obsługi kontekstu operacji.● Poszczególne bloki (funkcje) podlegające łączeniu przyjmują argument prosty (np. Int), zaś

zwracają wynik umieszczony w monadzie (np. Maybe Int).○ data Maybe a = Just a | Nothing

■ C++ → new, nullptr ■ Scala → Option (Some, None)

○ Przykładowa funkcja zwracająca indeks podanej liczby na liście będzie mieć sygnaturę indexOf :: Int -> [Int] -> Maybe Int

○ indexOf 12 [10,11,12,13] → Just 2

○ indexOf 12 [13,14,15,16] → Nothing

Page 28: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Monady - przykładPython

def f(x):

if x % 2 == 0: return x + 1

return None

def g(x):

if x % 3 == 0: return x + 2

return None

def h(x):

if x % 5 == 0: return x + 3

return None

def test(): return h(g(f(12)))

Haskell

f x

| x `mod` 2 == 0 = Just (x + 1)

| otherwise = Nothing

g x

| x `mod` 3 == 0 = Just (x + 2)

| otherwise = Nothing

h x

| x `mod` 5 == 0 = Just (x + 3)

| otherwise = Nothing

test = (h . g . f) 12

Page 29: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Monady - przykładPython

def f(x):

if x % 2 == 0: return x + 1

return None

def g(x):

if x % 3 == 0: return x + 2

return None

def h(x):

if x % 5 == 0: return x + 3

return None

def test(): return h(g(f(12)))

Haskell

f x

| x `mod` 2 == 0 = Just (x + 1)

| otherwise = Nothing

g x

| x `mod` 3 == 0 = Just (x + 2)

| otherwise = Nothing

h x

| x `mod` 5 == 0 = Just (x + 3)

| otherwise = Nothing

test = (h . g . f) 12

Page 30: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Monady - przykład (2)Python

def test():

x = f(12)

if x == None:

return None

else:

y = g(x)

if y == None:

return None

else:

z = h(y)

if z == None:

return None

else:

return z

Haskell

test =

case f 12 of

Nothing -> Nothing

Just x ->

case g x of

Nothing -> Nothing

Just y ->

case h y of

Nothing -> Nothing

Just z -> Just z

Page 31: Programowanie funkcyjne · Programowanie funkcyjne w języku Haskell λ Stanisław Wasik Na podstawie: St. Wasik, Programowanie funkcyjne w języku Haskell, Politechnika Poznańska,

Monady - przykład (3)Funkcja monadyczna >>= (bind)

a >>= f =

case a of

Nothing -> Nothing

Just x -> f x

test = Just 12 >>= f >>= g >>= h

albo krócej:

test = f 12 >>= g >>= h

Lista jako monada→ funkcja >>= odpowiada flatMap w języku Scala

f x

| x > 1 = [-x, x]

| otherwise = []

map f [1,2,3]

→ [[], [-2, 2], [-3, 3]]

[1,2,3] >>= f

→ [-2, 2, -3, 3]