In Haskell, le classi sono collezioni (o classificazioni) di tipi, analogamente a come i tipi sono collezioni di valori. Questa classificazione è di natura algebrica: una classe stabilisce un contratto (simile alle interfacce Java) che definisce quali operazioni un tipo deve supportare.
L’annotazione prima della freccia => indica un vincolo di classe.
Esempio: mcd :: (Ord a, Num a) => a -> a -> a.
Qui a non è un tipo arbitrario, ma deve essere contemporaneamente un sottotipo diOrd (per usare < e ==) e di Num (per usare -).
Anche le costanti hanno tipi vincolati: 3 :: Num a => a (può essere Int o Float, ma non Char).
Classi Predefinite
Le classi possono contenere codice predefinito (implementazioni di default) per i loro metodi
Eq (Equality Types)
Definisce l’uguaglianza (==) e la disuguaglianza (/=).
class Eq a where (==), (/=) :: a -> a -> Bool -- Implementazione di default per /= x /= y = not (x == y)
È sufficiente fornire il codice per ==, poiché /= è derivato.
Ord (Ordered Types)
Sottoclasse di Eq per tipi i cui valori sono ordinabili. È sufficiente fornire il codice per <, poiché gli altri operatori sono interdefiniti.
class Eq a => Ord a where (<),(<=),(>=),(>) :: a -> a -> Bool min, max :: a -> a -> a min x y | x <= y = x | otherwise = y max x y | x <= y = y | otherwise = x x <= y = x < y || x == y x >= y = x > y || x == y x > y = y >= x && y /= x
Num, Show e Read
Num: Classe generica per tipi numerici che supportano (+), (-), (*), abs, signum.
Show: Per convertire valori in String (show :: a -> String). Fondamentale per la stampa nell’interprete.
Read: Il duale di Show, converte una String in un valore (read :: String -> a).
Definizione di Nuovi Tipi e Sinonimi
Haskell offre due modi principali per nominare i tipi:
Sinonimi di Tipo ( type)
Crea alias per tipi esistenti. Non offre protezione sui dati (vige l’equivalenza strutturale) e non permette di definire nuove istanze.
type Casella = (Int, Int)
type PairH a = (a, a) (Sinonimo parametrico)
Nuovi Tipi di Dato ( data)
Definisce un tipo completamente nuovo tramite costruttori. Solo questi tipi possono essere dichiarati istanze di una classe.
Tipi Enumerati: data Giorni = Lun | Mar | Mer | Gio | Ven | Sab | Dom.
Tipi Parametrici: data Maybe a = Just a | Nothing.
Tipi Ricorsivi: data Nat = Zero | Succ Nat.
Istanze e Derivazione (deriving)
Derivazione Automatica
Per le classi standard (Eq, Ord, Show, Read, Enum), Haskell può generare automaticamente il codice tramite la clausola deriving.
L’uguaglianza derivata è sintattica.
L’ordinamento segue la posizione dei costruttori nella definizione.
Esempio Completo: Il tipo Giorni
data Giorni = Lun | Mar | Mer | Gio | Ven | Sab | Dom deriving (Eq, Ord, Show, Enum, Read)-- Esempi di utilizzo:lavorativi = [Lun .. Ven] -- Grazie a Enum-- > [Lun, Mar, Mer, Gio, Ven]g = read "Lun" :: Giorni -- Grazie a Read (richiede annotazione)-- > Lundomanda = Sab > Ven -- Grazie a Ord (Sab viene dopo Ven)-- > True
Dichiarazione Manuale di un'Istanza
Se vogliamo un comportamento personalizzato (es. una stampa diversa), usiamo instance:
instance Show Giorni where show Lun = "Lunedì" show _ = "Altro giorno"
Costruttori di Tipo Avanzati
Il tipo Maybe
Usato per computazioni che possono fallire o produrre eccezioni.
data Maybe a = Just a | NothingsafeDiv n 0 = NothingsafeDiv n m = Just (n `div` m)
Il tipo Either
Rappresenta somme disgiunte, utile per valori che possono essere di due tipi diversi (es. un numero o una funzione).
data Either a b = Left a | Right b-- Esempio: nodi di un albero di espressionitype Exp a = BinTree (Either (a -> a -> a) a)
Ecco la funzione di valutazione expEval.
expEval :: Num a => Exp a -> a expEval (R (Left f) l r) = f (expEval l) (expEval r) expEval (F (Right v)) = v
E la valutazione dell’espressione in figura è 42.
Tipi Induttivi e Ricorsione
Haskell eccelle nella gestione di strutture ricorsive come Liste e Alberi, definendo le funzioni per pattern matching sui costruttori.
Esempio definizione strutture ricorsve:
-- Lista Homemadedata List a = Nil | Cons a (List a)-- Alberi binari F=Foglia, R=radice data BTree a = Node a (BTree a) (BTree a) | Leaf a
Esempio definizione Funzioni:
-- Lunghezza di una lista length Nil = Zerolength (Cons _ l) = Succ (length l)-- append tra liste append l Nil = lappend Nil l = l append (Cons x l) m = Cons x (append l m)-- visita inorder di un albero binario flatten EMPTY = Nilflatten (Node x t1 t2) = append (flatten t1) (Cons x (flatten t2))