Both sides previous revision
Poprzednia wersja
Nowa wersja
|
Poprzednia wersja
|
pl:dydaktyka:pp:haskell:lab-monads-types [2018/05/24 02:02] esimon [Zadania] |
pl:dydaktyka:pp:haskell:lab-monads-types [2020/04/19 22:33] msl usunięto |
====== Monady i Typy ====== | ====== Typy ====== |
===== Wprowadzenie ===== | ===== Wprowadzenie ===== |
| |
W Haskellu mamy do czynienia z typowaniem statycznym. Oznacza to, ze już podczas kompilacji typ każdego z wyrażeń jest znany. | W Haskellu mamy do czynienia z typowaniem statycznym. Oznacza to, ze już podczas kompilacji typ każdego z wyrażeń jest znany. |
| |
W odróżnieniu jednka od standardowych języków programowania (np. Java), Haskell posiada mechanizm inferencji typów, co pozwala kompilatorowi wywnioskować typy wyrażeń, np: | W odróżnieniu jednak od standardowych języków programowania (np. Java), Haskell posiada mechanizm inferencji typów, co pozwala kompilatorowi wywnioskować typy wyrażeń, np: |
| |
<code haskel> | <code haskel> |
</code> | </code> |
| |
Podobnie w przypadku funkcji, chociaż tutaj zaleca sie stosowanie deklaracji explicite, chyba że tworzymy bardzo proste funkcjie, np: | Podobnie w przypadku funkcji, chociaż tutaj zaleca się stosowanie deklaracji explicite, chyba że tworzymy bardzo proste funkcje, np: |
| |
<code haskell> | <code haskell> |
| |
| |
Widzimy tutaj ciekaą rzecz. Sygnatura funkcji została poprawnie rozwinięta, ale Nie mamy tutaj żadnego konkretnego typu, znanego z innych językóœ progrmowania (Int, Float, Double). Zamiast tego mamy `a -> a -> Bool`. Jedynie typ wynikowy wygląda znajomo. | Widzimy tutaj ciekawą rzecz. Sygnatura funkcji została poprawnie rozwinięta, ale nie mamy tutaj żadnego konkretnego typu, znanego z innych języków programowania (Int, Float, Double). Zamiast tego mamy ''%%a -> a -> Bool%%''. Jedynie typ wynikowy wygląda znajomo. |
Po lewej stronie tego wyrażenia, tuż przed `==>` pojawia się tzw. Ograniczenie klasy `Ord a` wymuszające, że typ wejścia dla tej funkcji musi implementować //interfejs// `Ord`. Do poczytanie o ograniczeniach było na Lab2 (zobacz: ). | Po lewej stronie tego wyrażenia, tuż przed ''%%=>%%'' pojawia się tzw. ograniczenie klasy ''Ord a'' wymuszające, że typ wejścia dla tej funkcji musi implementować //interfejs// ''Ord''. Do poczytanie o ograniczeniach było na Lab 2 (dla przypomnienia, [[http://learnyouahaskell.com/types-and-typeclasses|tutaj jest ten link do podręcznika]]). |
| |
Pozwala to na pewnego rodzaju metaprogramowanie na poziomie typów. | Pozwala to na pewnego rodzaju metaprogramowanie na poziomie typów. |
==== Definiowanie własnych type-classes ==== | ==== Definiowanie własnych type-classes ==== |
| |
Możemy oczywiście definiować własne //interfejsty// dla typów, czyli type-classy i dziedziczyć istniejące. | Możemy oczywiście definiować własne //interfejsy// dla typów, czyli type-classy i dziedziczyć istniejące. |
Co więcej, mozna je aplikować do istniejących typów. | Co więcej, mozna je aplikować do istniejących typów. |
| |
<code haskell> | <code haskell> |
| {-# LANGUAGE FlexibleInstances #-} |
| |
class Listable a where | class Listable a where |
toList :: a -> [Int] | toList :: a -> [Int] |
| |
==== Definiowanie własnych typów ==== | ==== Definiowanie własnych typów ==== |
W haskelu robimy to za pomoca słowa kluczowego data. | W Haskellu robimy to za pomocą słowa kluczowego data. |
Na przykład, aby zdefiniować typ opisujący punkt w przesrtzeniu 2D: | Na przykład, aby zdefiniować typ opisujący punkt w przestrzeni 2D: |
| |
<code haskell> | <code haskell> |
Z takim type niewiele da sie zrobić. Nie da sie go nawet wyświetlić, ponieważ aby być wyświetlanym typ musi //implementować interfejs// Show, czyli dziedziczyć go. | Z takim type niewiele da sie zrobić. Nie da sie go nawet wyświetlić, ponieważ aby być wyświetlanym typ musi //implementować interfejs// Show, czyli dziedziczyć go. |
| |
Na szczęscie możliwe jest dziedziczenie typów. | Na szczęście możliwe jest dziedziczenie typów. |
| |
<code haskell> | <code haskell> |
</code> | </code> |
| |
==== Monady ==== | ==== Abstrakcyjne Typy Danych ==== |
Monady w Haskellu to konstruktory polimorficznych typów. | Abstrakcyjne typy danych w Haskellu to konstruktory polimorficznych typów. |
Typy takie mogą przechowywaćć wartości wielu różnych typów. | Typy takie mogą przechowywać wartości wielu różnych typów. |
| Przykładem takiego typu jest monada Maybe, definiowana jako |
Najczęsciej używana monadą jest Maybe, definiowana jako | |
| |
<code haskell> | <code haskell> |
</code> | </code> |
| |
Pozwala tworzyć pewnego rodzaju wrapper wokół typu, któ©y w zależnośći od tego jak pójdą obliczenia, //wyrzuci// ten typ, albo Nothing, ale nadal interpretowany jako Maybe. | Pozwala tworzyć pewnego rodzaju wrapper wokół typu, który w zależności od tego jak pójdą obliczenia, //wyrzuci// ten typ, albo Nothing, ale nadal interpretowany jako Maybe. |
| |
<code haskell> | <code haskell> |
| |
===== Zadania ===== | ===== Zadania ===== |
- Wykorzystując wiedzę o tym jak tworzyć typeclassy, stwórz jedną o nazwie Intable, która pozwoli na konwersję [Char] to Int poprzez funkcję toInt:<code haskell> | - Wykorzystując wiedzę o tym jak tworzyć typeclassy, stwórz jedną o nazwie Intable, która pozwoli na konwersję [Char] to Int poprzez funkcję toInt. Użyj jej jako ograniczenie w funkcji mySuperAdd:<code haskell> |
mySuperAdd (Intable a) ==> a->a->Int | mySuperAdd :: (Intable a, Intable b) => a -> b -> Int |
mySuperAdd x y = toInt x + toInt y | mySuperAdd x y = toInt x + toInt y |
mySuperAdd "123" + "12" | ghci> mySuperAdd "123" "12" |
mySuperAdd "123" + (12::IN=nt) | 135 |
| ghci> mySuperAdd "123" (12::Int) |
| 135 |
</code> | </code> |
- Zbuduj nowy typ Osoba, zawierający imię, nazwisko, pesel. Napisz typeclase umożliwiającą porównywanie osób (po peselu) i sortowanie po nazwisku. Czy da się wyświetlić osobę? Co gdyby dziedziczyć po Eq i Ord? Jak zachowywałoby się porównywanie `==,<=` ?Poniższe powinny działać poprawnie:<code haskell> | - Zbuduj nowy typ Osoba, zawierający imię, nazwisko, pesel. Napisz typeclase umożliwiającą porównywanie osób (po peselu) i sortowanie po nazwisku. Czy da się wyświetlić osobę? Co gdyby dziedziczyć po Eq i Ord? Jak zachowywałoby się porównywanie ''%%==,<=%%''? Poniższe powinny działać poprawnie:<code haskell> |
let szymon = Osoba "Szymon" "Bobek" "12345678901" | let szymon = Osoba "Szymon" "Bobek" "12345678901" |
let bobek = Osoba "S" "Bobek" "12345678901" | let bobek = Osoba "S" "Bobek" "12345678901" |
let zenon = Osoba Zenon Adamczyk "111111111" | let zenon = Osoba "Zenon" "Adamczyk" "111111111" |
ghci> szymon == bobek | ghci> szymon == bobek |
True | True |
ghci> szymon > zenon | ghci> szymon > zenon |
True</code> | True</code> |
| - Zaimplementuj funkcję, która będzie wykonywać pewien predykat na elementach listy i w przypadku gdy predykat zwróci True, funkcja zwróci dany element listy, lub Nothing jeśli predykat nie zakończy się True na żadnym z elementów listy. Np. możesz użyć predykatu porównującego osoby po peselu co umożliwi wyszukiwanie pierwszej osoby w liście o danym peselu. |
- Zaimplementuj drzewo binarne umożliwiające przechowywanie dowolnych typów, tak aby dało sie stworzyć je w następujący sposób:<code haskell> | - Zaimplementuj drzewo binarne umożliwiające przechowywanie dowolnych typów, tak aby dało sie stworzyć je w następujący sposób:<code haskell> |
myTree :: Tree Int | myTree :: Tree Int |
myTree = Node 1 (Node 2 Empty (Node 3 Empty Empty)) (Node 4 Empty Empty) | myTree = Node 3 (Node 1 Empty (Node 2 Empty Empty)) (Node 4 Empty Empty) |
</code> | </code> |
- insert (wstawienie elementu) | - insert (wstawienie elementu) |
- empty (sprawdzanie czy drzewo jest puste) | - empty (sprawdzanie czy drzewo jest puste) |
- isBinary (sprawdzenie czy drzewo jest drzewem binarnym) | |
- search (sprawdzanie czy element jest w drzewie) | - search (sprawdzanie czy element jest w drzewie) |
- toString (wypisującą drzewo w postaci „a(b(d,e),c(,f(g,)))” ) | - toString (wypisującą drzewo w postaci „a(b(d,e),c(,f(g,)))” ) |
- nsum (zliczającą sumę wartości w węzłach) | - nsum (zliczającą sumę wartości w węzłach) |
- remove (usuwanie elementu)* | - remove (usuwanie elementu)* |
| |
| |
| |