140 likes | 420 Views
Haskell: Tipi algebrici. Tipi algebrici: proprietà, sintassi, semantica Tipi algebrici: esempi e applicazioni Esempi: Tipi algebrici polimorfi Equivalenza strutturale e refenziale: vantaggi Morfismi tra tipi: Deriving e esplicito Tipi ricorsivi e mutuamente ricorsivi
E N D
Haskell: Tipi algebrici • Tipi algebrici: proprietà, sintassi, semantica • Tipi algebrici: esempi e applicazioni • Esempi: Tipi algebrici polimorfi • Equivalenza strutturale e refenziale: vantaggi • Morfismi tra tipi: Deriving e esplicito • Tipi ricorsivi e mutuamente ricorsivi • Tipo unione (disgiunta): Either e Maybe • Induzione strutturale • Esercizi
T1,1 x … x Cn1,1 + Tn1,1 N + Cnk,k Tnk,1 x … x Tnk,k Proprietà: sintassi e semantica • Due forme per introdurre tipi espliciti: • Sinonimi • type People = (Name, Age) type Name = String type Age = Int • Algebrici • data People = Person Name Age data Name = LastFisrt String data Age = Year Int • Struttura Sintattica • data Name = Constrn1,1 eT1,1 … eTn1,1 | … | Constrnk,k eTk,1 … eTnk,k • Significato • data N = Cn1,1 eT1,1…eTn1,1 | … | Cnk,k eTk,1…eTnk,k • definisce iniezioni da domini somme di prodotto
Struttura: Esempi e applicazioni • Tipi enumerati • data Tepore = Caldo | Freddo • data Stagioni = Autunno | Inverno | Primavera | Estate • unione di tipi il cui dominio di valori contiene un solo valore • ogni valore è un costruttore • Tipi prodotto • data Persona = Person PNome PEta • data PNome = Coppia Cognome Nome • data PEta = Anni Int • prodotto di tipi • ogni valore è una iniezione di un prodotto di valori • Tipi unione • data IntErr = Val Int | Err String
Esempi: Tipi algebrici polimorfi Lisp: S-espessioni data SExpr = A Atom | Cons SExpr SExpr deriving(Show, Eq) data Atom = LAMBDA | VAL Int | VAR String deriving(Show, Eq) fun = Cons (A LAMBDA) (Cons (Cons (A(VAR "X")) (A(VAR "y"))) (A(VAR "y"))) Alberi polimorfi data Tree a = Nil | Node a (Tree a) (Tree a) deriving(Show,Eq,Ord) t1 = Node “uno” (Node “due” (Node “tre” Nil Nil) Nil) Nil t2 = Node “uno” Nil (Node “due” (Node “tre” Nil Nil) Nil) t1 > t2
Equivalenza strutturale e nominale • Due forme per introdurre tipi espliciti: • Sinonimi • type People = (Name, Age) type Name = String type Age = Int • Algebrici • data People = Person Name Age data Age = Year Int • Due forme di equivalenza di tipo • Sinonimo: equivalenza strutturale • x:: People; y:: (String,Int) --- x e y hanno stesso tipo • Algebrico:equivalenza nominale (referenziale) • Ogni tipo algebrico è unico • Vantaggi: Sinonimi • Defnizione compatta: dovuta all’uso di strutture built-in quali le tuple • Riusabilità: dovuta alla equivalenza strutturale Algebrici: • Morfismi: possibilità di morfismi tra tipi (deriving istanze di classe) • Tipi ricorsivi: sono ilmeccanismo per introdurre tipi ricorsivi • Uso di nomi: (significativi) per i selettori dei componenti -- esempio: CognomeNome String String • Riduzione di errori: dovuta all’equivalenza nominale che previene l’uso improprio di tipi diversi • Documentazione: dovuta ad un buon uso di nomi -- esempio: Year Int
Morfismi tra tipi: deriving • Morfismi tra tipi basati sui costruttori op: A --> B data TA = CA A data TB = CB B (A-->B)->(Ta-->Tb)(op u) = op (CA v) = CB(op v) Quando op preserva i morfismi -- class AB a where op:: A-->B • In Haskell: il costrutto deriving (solo per built-in) • data Stagioni = Autunno | Inverno | Primavera | Estate Deriving (Eq, Ord, Enum, Show) Equivale a: instance Eq Stagioni where Autunno == Autunno = True …; instance Ord Stagioni where Autunno > Inverno = True … ; instance …
Morfismi tra tipi: esplicito • Scenario iniziale: due classi e due tipi class Movable a where reflectX:: a -> a --- ed altre operazioni che omettiamo data AName = Pair A String • Come esprimere un morfismo Movable A --> Movable Pair A String • passo1: lifting di funzioni A->A su (AName)->(AName) mapName f (Pair a s) = Pair (f a) s esempio: reflectX:: a --> a mapAName reflectX:: AName --> AName • passo2(ultimo): AName è un movable quando A è movable instance Movable A => Movable AName where reflectX = mapAName reflectX esempio: instance Movable A where reflectX u = …. ora possiamo esprimere e calcolare: reflectX (P v s) con v espressione di tipo A ed s espressione di tipo String
Morfismi tra tipi polimorfi: esplicito • Scenario iniziale: due classi e due tipi class Movable a where reflectX:: a -> a --- ed altre operazioni che omettiamo data Name a = Pair a String • Come esprimere un morfismo Movable a --> Movable Pair a String • passo1: lifting di funzioni a->a su (Name a)->(Name a) mapName f (Pair a s) = Pair (f a) s esempio: reflectX:: a --> a mapName reflectX:: (Name a) --> (Name a) • passo2(ultimo): Name a è un movable quando a è movable instance Movable a => Movable (Name a) where reflectX = mapName reflectX esempio: instance Movable A where reflectX u = …. ora possiamo esprimere e calcolare: reflectX (P v s) con v espressione di tipo A ed s espressione di tipo String
Esempi: Tipi algebrici polimorfi Lisp: S-espessioni data SExpr = A Atom | Cons SExpr SExpr deriving(Show, Eq) data Atom = LAMBDA | VAL Int | VAR String deriving(Show, Eq) fun = Cons (A LAMBDA) (Cons (Cons (A(VAR "X")) (A(VAR "y"))) (A(VAR "y"))) Alberi polimorfi data Tree a = Nil | Node a (Tree a) (Tree a) deriving(Show,Eq,Ord) t1 = Node “uno” (Node “due” (Node “tre” Nil Nil) Nil) Nil t2 = Node “uno” Nil (Node “due” (Node “tre” Nil Nil) Nil) t1 > t2
Tipi ricorsivi e mutuamente ricorsivi • data IntList = Val Int | Cons Int IntList • data Expr = Lit Int | Expr :+: Expr | Expr :-: Expr • data SForest = P TLabel [Stree] data STree = Leaf NLabel | Root Sforest data TLabel = T String data NLabel = N Label Anche polimorfe: RISCRIVIAMOLE
Tipo unione: Either e Maybe Either data Either a b = Left a | Right b deriving(Show, Ord, Eq) compareMese::Either Int String -> Either Int String -> Boolean Maybe data Maybe a = Nothing | Just a deriving(Show,Eq,Ord) factorial n |(n < 0) = Nothing |(n==0) = Just 1 |otherwise= let Just m = factorial (n-1) in Just (n* m)
(1) (2) Induzione strutturale Un tipo algebrico (polimorfo su a) data TyName a = C1 a | … | Ck a esempio: data Tree a = Nil | Node a (Tree a) (Tree a) Una proprietà su TyName v::TyName, P(v) esempio: A| v::Tree a, C(v) dove, A: flipT Nil = Nil flipT(Node u t1 t2) = Node u (flipT t2) (flipT t1) C(v): flipT(flipT v) = v Dimostrazione: Induzione sulla struttura Base: Nil --- (componenti non ricorsivi) v=Nil => flipT(flipT Nil) = flipT Nil = Nil Generale: vero per t1,t2, --- (termini dei componenti ricorsivi) i.e. A|flipT(flipT t1))=t1 & flipT(flipT t2))=t2 --- (ind. Hyp.) v = Node u t1 t2 => flipT(flipT(Node u t1 t2)) = flipT(Node u (flipT t2) (flipT t1)) --- (by 2) = Node u (flipT(flipT t1)) (flipT(flipT t2)) --- (by 2) = Node u t1 t2 --- (by ind. Hyp.)
Esercizi: • Polimorfi: Si ridefinisca il tipo Expr in un polimorfo che generalizzi Int. Si ridefisnisca il tipo Sforest (ed tipi correlati) in un polimorfo che astragga rispetto ad una variabile a per il tipo delle etichette dei nodi interni e una b per i nodi foglia. Si definisca, quindi una funzione sizeIn che calcoli il numero di nodi interni di una SForest • Show: Per il polimorfo Sforest precedente si provveda a definire l’operazione show, ricorrendo: • 1) ora al morfismo implicito, • 2) ora a quello esplicito. In quest’ultimo caso, la stringa di presentazione deve essere una sequenza racchiusa tra parentesi tonde e contenente le presentazione degli alberi, a loro volte sequenze, senza separatori. • Tipi: Si definisca un tipo di dato per memorie rappresentate come funzioni da Location -> Val, dove Val sia un tipo adatto per esprimere 3 possibili differenti tipi di valore e Location sia un tipo per locazioni raprresenta- bili con arbitari interi. Si definisca l’operazione alloc che data una Location e un tipo dei tre possibili allochi in memoria tale locazioni con valore il valore di default previsto per tale tipo. • Tipi: Si definisca un tipo di dato per insiemi polimorfi e lo si equipaggi con le operazioni di unione, appartenenza, e confronto, > e ==. • Tipi: Si definisca un tipo di dato per relazioni binarie polimorfe rispetto ad un tipo a di classe Ord. Si fornisca la definizione di un predicato transitive che calcola true se e solo se la relazione è transitiva, e la definizione della funzione min che, data una relazione e un valore u, calcola il minimo valore che è in relazione con u.
Briciole:Tipi ricorsivi e domini riflessivi data Rec a = R ((Rec a) -> (Rec a)) unfoldRec (R f) = f foldRec (R f) x = f x -- typing \x -> (x x) funXX:: Rec a -> Rec a funXX = \x -> foldRec x x -- typing Y=\f -> (\x -> f x x) (\x -> f x x), s.t. Y F = f(Y F)