Estoy tratando de comprender GADTs
, y he visto el GADTs example en el manual de GHC. Por lo que yo puedo decir, que es posible hacer lo mismo con MultiParamTypeClasses
:GADTs frente a 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, que tenemos exactamente los mismos constructores y el mismo código exacto para eval
(diseminación cruzar las definiciones de instancia) como en Ejemplo de GADTs
de GHC.
Entonces, ¿qué es todo el pelusa sobre GADTs
? ¿Hay algo que pueda hacer con GADTs
que no puedo hacer con MultiParamTypeClasses
? ¿O simplemente ofrecen una forma más concisa de hacer las cosas que yo podría hacer con MultiParamTypeClasses
?
En su ejemplo, usted puede construir 'If (Lit 3) (IntTerm 1) (IntTerm 2)'. Considere el uso de 'data If a = If BoolTerm a a'. – ony
GADTs no ofrecen nada que no pueda ser simulado por tipos existenciales y tipo de igualdad. Pero su ejemplo particular no es una instancia de esto. – augustss
Las GADT están cerradas en el momento de la definición, lo que puede ser una gran diferencia. –