Sto cercando di afferrare GADTs
e ho guardato il GADTs example nel manuale di GHC. Per quanto posso dire, è possibile fare la stessa cosa con MultiParamTypeClasses
:GADTs vs MultiParamTypeClasses
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies,
FlexibleInstances, UndecidableInstances #-}
class IsTerm a b | a -> b where
eval :: a -> b
data IntTerm = Lit Int
| Succ IntTerm
data BoolTerm = IsZero IntTerm
data If p a = If p a a
data Pair a b = Pair a b
instance IsTerm IntTerm Int where
eval (Lit i) = i
eval (Succ t) = 1 + eval t
instance IsTerm BoolTerm Bool where
eval (IsZero t) = eval t == 0
instance (IsTerm p Bool, IsTerm a r) => IsTerm (If p a) r where
eval (If b e1 e2) = if eval b then eval e1 else eval e2
instance (IsTerm a c, IsTerm b d) => IsTerm (Pair a b) (c, d) where
eval (Pair e1 e2) = (eval e1, eval e2)
nota, che abbiamo gli stessi costruttori esatte e lo stesso codice esatto per eval
(spread attraversare le definizioni esempio) come in Esempio di GHC GADTs
.
Quindi cos'è tutta la fuzz su GADTs
? C'è qualcosa che posso fare con GADTs
che non posso fare con MultiParamTypeClasses
? Oppure forniscono semplicemente un modo più conciso di fare cose che potrei fare con MultiParamTypeClasses
?
Nel tuo esempio sei in grado di costruire 'If (Lit 3) (IntTerm 1) (IntTerm 2)'. Prendi in considerazione l'uso di 'data If a = If BoolTerm a a'. – ony
GADT non offrono nulla che non possa essere simulato da tipi esistenziali e tipo uguaglianza. Ma il tuo esempio particolare non è un'istanza di questo. – augustss
Le GADT sono chiuse al momento della definizione, che può essere una grande differenza. –