Uivatelem definovan typy Ing Lumr Nvrat katedra informatiky

  • Slides: 31
Download presentation
Uživatelem definované typy Ing. Lumír Návrat katedra informatiky, A 1018 59 732 3252 FLP

Uživatelem definované typy Ing. Lumír Návrat katedra informatiky, A 1018 59 732 3252 FLP - Uživatelem definované typy

Definice uživatelského typu l data Color = Red | Green | Blue l l

Definice uživatelského typu l data Color = Red | Green | Blue l l l data Point = Point Float l l l Color – typový konstruktor Red / Green / Blue – datové konstruktory dist (Point x 1 y 1) (Point x 2 y 2) = sqrt ((x 2 -x 1)**2 + (y 2 -y 1)**2) dist (Point 1. 0 2. 0) (Point 4. 0 5. 0) = 5. 0 data Point a = Point a a l l polymorfismus konstruktor Point : : a -> Point a FLP - Uživatelem definované typy 2

Součinové datové typy l data Point = Point Int l l existuje jen jediná

Součinové datové typy l data Point = Point Int l l existuje jen jediná varianta typová kontrola v době překladu žádná kontrola v době běhu data Dvojice a b = Dvojice a b type Dvojice a b = (a, b) l izomorfní s uspořádanými n-ticemi FLP - Uživatelem definované typy 3

Součtové datové typy l data Color = Red | Green | Blue l l

Součtové datové typy l data Color = Red | Green | Blue l l l existuje více variant každá varianta je součinovým typem nutnost kontroly v době běhu is. Red : : Color -> Bool is. Red = True l může nastat chyba: is. Red Blue = ? ? ? FLP - Uživatelem definované typy 4

Rekurzivní datové typy Seznam data List a = Null | Cons a (List a)

Rekurzivní datové typy Seznam data List a = Null | Cons a (List a) lst : : List Int lst = Cons 1 (Cons 2 (Cons 3 Null)) append Null ys = ys append (Cons x xs) ys = Cons x (append xs ys) FLP - Uživatelem definované typy 5

Rekurzivní datové typy Strom data Tree 1 a = | data Tree 2 a

Rekurzivní datové typy Strom data Tree 1 a = | data Tree 2 a = | data Tree 3 a = | Leaf a Branch (Tree 1 a) Leaf a Branch a (Tree 2 a) Null Branch a (Tree 3 a) t 2 l (Leaf x) = [x] t 2 l (Branch lt rt) = (t 2 l lt) ++ (t 2 l rt) FLP - Uživatelem definované typy 6

Synonyma datových typů l type String = [Char] type Name = String data Address

Synonyma datových typů l type String = [Char] type Name = String data Address = None | Addr String type Person = (Name, Address) type Table a = [(String, a)] l l jsou ekvivalentní původním typům představují pouze zkratky FLP - Uživatelem definované typy 7

Zavedení nového typu l newtype Natural = Make. Natural Int l l není ekvivalentní

Zavedení nového typu l newtype Natural = Make. Natural Int l l není ekvivalentní původnímu typu Int vyžaduje explicitní konverzní funkce to. Natural : : Int -> Natural to. Natural x | x < 0 = error “Chyba” | otherwise = Make. Natural x from. Natural : : Natural -> Int from. Natural (Make. Natural x) = x FLP - Uživatelem definované typy 8

Pojmenované složky typů l Selektor – vrací složku hodnoty l l data Point =

Pojmenované složky typů l Selektor – vrací složku hodnoty l l data Point = Pt Float px : : Point -> Float px (Pt x y) = x Pojmenované složky = selektory l data Point = Pt { px, py : : Float } abs (Pt px=x, py=y) = sqrt (x*x+y*y) abs p = sqrt ((px p)**2 + (py p)**2) l Vytvoření modifikované kopie l p { px = x } FLP - Uživatelem definované typy 9

Motivace l Funkce elem. Bool l l Funkce elem. Int l l elem. Bool

Motivace l Funkce elem. Bool l l Funkce elem. Int l l elem. Bool : : Bool -> [Bool] ->Bool elem. Bool x [] = false elem. Bool x (y: ys) = (x ==Bool y) || elem. Bool x ys elem. Int : : Int -> [Int] ->Bool Funkce elem. Gen l l elem. Gen : : (a ->Bool) -> a -> [a] -> Bool elem. Gen (==Bool) FLP - Uživatelem definované typy 10

Řešení ? l Funkce elem l l Výhody l l l elem : :

Řešení ? l Funkce elem l l Výhody l l l elem : : a -> [a] -> Bool Znovupoužitelnost Adaptibilita Nevýhody l Jak omezit na porovnatelné typy? elem sin [sin, cos, tg] -> co je výsledek? l Řešení l elem : : Eq a => a -> [a] -> Bool FLP - Uživatelem definované typy 11

Typové třídy l Kontext (C 1 a, C 2 b, …), resp. C a

Typové třídy l Kontext (C 1 a, C 2 b, …), resp. C a l l l omezení na typové proměnné a, b, . . . C 1 , C 2. . . jsou typové třídy Typ u. cx => t l l u – typové proměnné cx – kontext t – typový výraz Př. : Eq a => a -> [a] -> Bool (Eq a, Num b) => (a, b) -> [a] FLP - Uživatelem definované typy 12

Definice typové třídy l Definice signatury metod a implicitní metody l l class Eq

Definice typové třídy l Definice signatury metod a implicitní metody l l class Eq a where (==), (/=) : : a -> Bool x == y = not (x /= y) x /= y = not (x == y) Dědičnost l l class (Eq a) => Ord a where (<), (<=), (>=) : : a -> Bool max, min : : a -> a class (Read a, Show a) => Textual a FLP - Uživatelem definované typy 13

Definice instance typové třídy instance Eq Int where x == y = int. Eq

Definice instance typové třídy instance Eq Int where x == y = int. Eq x y instance Eq a [] == (x: xs) == _ == => Eq [a] where [] = True (y: ys) = x == y && xs == ys _ = False instance (Eq q, Eq b) => Eq (a, b) where (x 1, y 1) == (x 2, y 2) = x 1==x 2 && y 1==y 2 FLP - Uživatelem definované typy 14

Základní typové třídy Eq a (==), (/=) Eq a => Ord a (<), (<=),

Základní typové třídy Eq a (==), (/=) Eq a => Ord a (<), (<=), (>=), min, max Enum a succ, pred Read a reads. Prec Show a shows. Pres, show (Eq a, Show a) => Num a (+), (-), (*), negate, abs (Num a) => Fractional a (/), recip (Fractional a) => Floating a pi, exp, log, sqrt, (**), … FLP - Uživatelem definované typy 15

Hierarchie tříd FLP - Uživatelem definované typy 16

Hierarchie tříd FLP - Uživatelem definované typy 16

Třída Show l Hodnoty převoditelné na řetězec l l l type Show. S =

Třída Show l Hodnoty převoditelné na řetězec l l l type Show. S = String -> String class Show a where shows. Prec : : Int -> a -> Show. S show : : a -> String show. List : : [a] -> Show. S show. Point : : Point -> String show. Point (Pt x, y) = “(“ ++ show x ++ ”; ” ++ show y ++ ”)” instance Show Point where show p = show. Point p FLP - Uživatelem definované typy 17

Třída Read l Hodnoty převoditelné z řetězce l type Read. S a = String

Třída Read l Hodnoty převoditelné z řetězce l type Read. S a = String -> [(a, String)] class Read a where reads. Prec : : Int -> Read. S a read. List : : Read. S [a] l reads. Point : : Read. S Point reads. Point (‘(‘: s) = [ (Pt x y, s’’) | (x, ’; ’: s’) <- reads s, (y, ‘)’: s; ; ) <- reads s’] l instance Read Point where reads. Prec _ = reads. Point FLP - Uživatelem definované typy 18

Moduly l l Definice modulu l module A where. . . -- A. hs,

Moduly l l Definice modulu l module A where. . . -- A. hs, A. lhs l všechny definice jsou viditelné Import modulu l module A where import B. . . l dovezou se všechny viditelné definice FLP - Uživatelem definované typy 19

Moduly l Omezení exportu l l l module Expr ( print. Expr, Expr(. .

Moduly l Omezení exportu l l l module Expr ( print. Expr, Expr(. . ) ) where Expr(. . ) – exportuje i konstruktory Expr – pouze export jména typu Omezení dovozu l l l import Expr hiding( print. Expr ) import qualified Expr -- Expr. print. Expr import Expr as Vyraz -- Vyraz. print. Expr FLP - Uživatelem definované typy 20

Motivace l Cíl: Vytvoření kalkulátoru pro číselné výrazy l l Modely zapisovatelné paměti l

Motivace l Cíl: Vytvoření kalkulátoru pro číselné výrazy l l Modely zapisovatelné paměti l l l čtení a zápis hodnot proměnných seznam dvojic: [(String, Int)] funkce: (String -> Int) Operace l l l initial : : Store value : : Store -> String -> Int update : : Store -> String -> Int -> Store FLP - Uživatelem definované typy 21

Abstraktní datový typ l Omezené rozhraní l l Nezávislost rozhraní na implementaci l l

Abstraktní datový typ l Omezené rozhraní l l Nezávislost rozhraní na implementaci l l type Store = [(Int, Var)] s 1, s 2: : Store -> Co je to s 1++s 2 ? type Store = Var -> Int s 1, s 2: : Store -> s 1++s 2 nefunguje Podmínky pro ADT l l definice veřejného rozhraní implementace typu není dostupná FLP - Uživatelem definované typy 22

ADT a Haskell l ADT je definován v samostatném modulu Explicitní export operací Export

ADT a Haskell l ADT je definován v samostatném modulu Explicitní export operací Export pouze jména typu bez konstruktorů module Store (Store, initial, -- Store value, -- Store -> String -> Int update -- Store -> String -> Int -> Store ) where FLP - Uživatelem definované typy 23

Implementace - seznam l l Definice typu data Store = Sto [(String, Int)] newtype

Implementace - seznam l l Definice typu data Store = Sto [(String, Int)] newtype Store = Sto [(String, Int)] Definice operací initial : : Store initial = Sto [] value : : Store -> String -> Int value (Sto []) _ = 0 value (Sto ((w, n): sto)) v | v == w = n | otherwise = value (Sto sto) v update : : Store -> String -> Int -> Store update (Sto sto) v n = Sto ((v, n): sto) FLP - Uživatelem definované typy 24

Implementace - funkce l Definice typu newtype Store = Sto (String -> Int) l

Implementace - funkce l Definice typu newtype Store = Sto (String -> Int) l Definice operací initial : : Store initial = Sto (v -> 0) value : : Store -> String -> Int value (Sto sto) v = sto v update : : Store -> String -> Int -> Store update (Sto sto) v n = Sto (w -> if v==w then n else sto w) FLP - Uživatelem definované typy 25

Obecné principy návrhu ADT l l l Identifikace a pojmenování typů Neformální popis typů

Obecné principy návrhu ADT l l l Identifikace a pojmenování typů Neformální popis typů Signatury typů l l l Jak vytvořit objekt daného typu? Jak zjistit, o jaký druh objektu jde? Jak se dostaneme ke složkám typu? Můžeme provádět transformace objektů? Jak můžeme objekty kombinovat? Můžeme objekty agregovat? FLP - Uživatelem definované typy 26

ADT Fronta l l inicializace: empty. Q test prázdné fronty: is. Empty. Q vložení

ADT Fronta l l inicializace: empty. Q test prázdné fronty: is. Empty. Q vložení na konec fronty: add. Q výběr prvku ze začátku fronty: rem. Q module Queue ( Queue, empty. Q, -- Queue a is. Empty. Q, -- Queue a -> Bool add. Q, -- a -> Queue a rem. Q -- Queue q -> (a, Queue a) ) where FLP - Uživatelem definované typy 27

Implementace fronty 1 -- vkládáme na konec, vybíráme ze začátku seznamu newtype Queue a

Implementace fronty 1 -- vkládáme na konec, vybíráme ze začátku seznamu newtype Queue a = Qu [a] empty. Q = Qu [] is. Empty. Q (Qu q) = empty q add. Q x (Qu xs) = Qu (xs++[x]) rem. Q q@(Qu xs) | not (is. Empty. Q q) = (head xs, Qu (tail xs)) | otherwise = error “rem. Q” FLP - Uživatelem definované typy 28

Implementace fronty 2 -- vkládáme na začátek, vybíráme z konce seznamu add. Q x

Implementace fronty 2 -- vkládáme na začátek, vybíráme z konce seznamu add. Q x (Qu xs) = Qu (x: xs) rem. Q q@(Qu xs) | not (is. Empty. Q q) = (last xs, Qu (init xs)) | otherwise = error “rem. Q” l složitost add. Q/rem. Q l konstantní – na začátku seznamu l lineární – na konci seznamu FLP - Uživatelem definované typy 29

Implementace fronty 3 newtype Queue a = Qu [a] empty. Q = Qu []

Implementace fronty 3 newtype Queue a = Qu [a] empty. Q = Qu [] [] is. Empty. Q (Qu [] []) = True is. Empty. Q _ = False add. Q x (Qu xs ys) = Qu xs (x: ys) rem. Q (Qu (x: xs) ys) rem. Q (Qu [] []) = (x, Qu xs ys) = rem. Q (Qu (reverse ys) []) = error “rem. Q” FLP - Uživatelem definované typy 30

Příklady pro cvičení 1) Vyhledání maximální hodnoty ve stromu l max. Tree : :

Příklady pro cvičení 1) Vyhledání maximální hodnoty ve stromu l max. Tree : : Ord a => Tree a -> a 2) Reprezentace aritmetického výrazu uživatelským datovým typem l data Expr = Plus Expr | … | Num Int 3) Vyhodnocení výrazu l eval : : Expr -> Int 4) Převod výrazu na řetězec l instance Show Expr where … FLP - Uživatelem definované typy 31