Both sides previous revision
Poprzednia wersja
Nowa wersja
|
Poprzednia wersja
|
pl:dydaktyka:pp:haskell:lab-monads [2020/05/25 03:48] msl [Notacja 'Do'] |
pl:dydaktyka:pp:haskell:lab-monads [2020/06/01 15:34] (aktualna) msl [Zadania:] |
==== Notacja 'Do' ==== | ==== Notacja 'Do' ==== |
| |
Operatory ''%%>>=%%'' i ''%%>>%%'' mają na celu tworzenia łańcuchów przekształceń danej monady, ale ich użycie jest dość niewygodne - szczególnie w przypadkach długich łańcuchów, w których są błędy. Dlatego powstała notacja ''do'', której używaliśmy na poprzednich zajęciach --- ''IO'' to też monada! Zacznijmy od w miarę złożonego łąńucha ''%%>>='': | Operatory ''%%>>=%%'' i ''%%>>%%'' mają na celu tworzenia łańcuchów przekształceń danej monady, ale ich użycie jest dość niewygodne - szczególnie w przypadkach długich łańcuchów, w których są błędy. Dlatego powstała notacja ''do'', której używaliśmy na poprzednich zajęciach --- ''IO'' to też monada! Zacznijmy od w miarę złożonego łąńucha ''%%>>=%%'': |
| |
<code haskell> | <code haskell> |
**Ćwiczenie:** spróbuj zrobić nieudany pattern matching w notacji ''do''. Jaki będzie efekt? | **Ćwiczenie:** spróbuj zrobić nieudany pattern matching w notacji ''do''. Jaki będzie efekt? |
| |
===== A po co to? ===== | ==== A po co to? ==== |
| |
Możliwość łańcuchowania operacji na monadach jest nie do przecenienia i aktualnie jest implementowana we wszystkich nowoczesnych językach programowania. Nie oznacza to, że dany język musi mieć wsparcie dla definiowania Monad tak jak Haskell. Poszczególne monady można implementować w Pythonie, Javie, etc. Po prostu nie ma tam takiego ogólnego mechanizmu jak ''typeclass'' do ujęcia wszystkich monad naraz. | Możliwość łańcuchowania operacji na monadach jest nie do przecenienia i aktualnie jest implementowana we wszystkich nowoczesnych językach programowania. Nie oznacza to, że dany język musi mieć wsparcie dla definiowania Monad tak jak Haskell. Poszczególne monady można implementować w Pythonie, Javie, etc. Po prostu nie ma tam takiego ogólnego mechanizmu jak ''typeclass'' do ujęcia wszystkich monad naraz. |
| |
Sławny i popularny przykład zastosowania monad to [[https://fsharpforfunandprofit.com/rop/|railway programming]], czyli funkcyjny sposób obsługi błędów. | Sławny i popularny przykład zastosowania monad to [[https://fsharpforfunandprofit.com/rop/|railway programming]], czyli funkcyjny sposób obsługi błędów. |
| |
| ===== Zadania: ===== |
| |
| Dzisiejsze zadania będą dotyczyć drzewa binarnego opisanego w następujący sposób: |
| |
| <code haskell> |
| data Tree a = Empty | Leaf a | Node (Tree a) (Tree a) |
| </code> |
| |
| - Zaimplementuj klasę ''Functor'' dla nowego typu ''Tree''. |
| - Zaimplementuj klasę ''Monad'' dla tego samego typu. |
| - Przeczytaj o monadzie [[http://learnyouahaskell.com/for-a-few-monads-more#state|State]]. Zaimplementuj poniższe operacje jako //stateful computations// dla **starego** drzewa z [[https://ai.ia.agh.edu.pl/pl:dydaktyka:pp:haskell:lab-types|poprzedniego laboratorium]]: |
| * insert - umieszcza element w drzewie |
| * removeAll - usuwa wszystkie elementy spełniające zadany warunek z drzewa i zwraca je w liście jako wynik |
| * search - sprawdza, czy element jest w drzewie |
| - Zadanie ekstra - zaimplementuj te same operacje dla nowego drzewa |
| * podpowiedź: {{tree.png?linkonly=yes}} |
| |
| <WRAP center round important 60%> |
| **UWAGA**: w zależności od wersji Haskella, może być konieczne również zaimplementowanie klasy ''Applicative'' (jako wymagania do bycia monadą). |
| Klasa ''Applicative'' umożliwa używanie funkcji opakowanych monadą. |
| |
| Poniżej jest przykładowa implementacja ''Applicative'', która jest poprawna, ale akceptuje tylko pojedyncze funkcje opakowane w liściach - na dzisiaj wystarczy: |
| * ''pure'' to dokładnie to samo, co ''return''. Tak naprawdę w Monadzie zawsze można pisać: ''return = pure'' |
| * ''%%<*>%%'' aplikuje funkcję opakowaną monadą, taki ''fmap'', który wyjmuje funkcję z pudełka, a nie ma go pod ręką |
| |
| <code haskell> |
| instance Applicative Tree where |
| pure x = Leaf x |
| _ <*> Empty = Empty |
| (Leaf f) <*> (Leaf x) = Leaf (f x) |
| (Leaf f) <*> (Node x y) = Node (fmap f x) (fmap f y) |
| </code> |
| |
| </WRAP> |
| |