{-# LANGUAGE GADTs, KindSignatures #-} module Expr0 where -- See Trac #301 -- This one *does* use GADTs (Fct) import Data.Kind (Type) data Expr :: Type -> Type where Const :: Show a => a -> Expr a Apply :: Fct a b -> Expr a -> Expr b data Fct :: Type -> Type -> Type where Succ :: Fct Int Int EqZero :: Fct Int Bool Add :: Fct Int (Int -> Int) ------------------------------ e1 :: Expr Int e1 = Apply Succ (Const 41) e2 :: Expr Bool e2 = Apply EqZero e1 e3 :: Expr (Int -> Int) e3 = Apply Add e1 ------------------------------ eval :: Expr a -> a eval (Const c) = c eval (Apply f a) = evalFct f $ eval a evalFct :: Fct a b -> a -> b evalFct Succ = succ evalFct EqZero = (0 ==) evalFct Add = (+) {- Up to here, everything works nicely: \begin{verbatim} *Expr0> eval e1 42 *Expr0> eval e2 False *Expr0> eval e3 5 47 \end{verbatim} But let us now try to define a |Show| instance. For |Fct|, this is not a problem: -} instance Show (Fct a b) where show Succ = "S" show EqZero = "isZero" show Add = "add" showsExpr :: Expr a -> ShowS showsExpr (Const c) = shows c showsExpr (Apply f a) = ('(' :) . shows f . (' ' :) . showsExpr a . (')' :) instance Show (Expr a) where showsPrec _ (Const c) = shows c showsPrec _ (Apply f a) = ('(' :) . shows f . (' ' :) . shows a . (')' :) {- But we used to get a complaint about the |Const| alternative (then line 56) that documents that the constraint in the type of |Const| must have been ignored: \begin{verbatim} No instance for (Show a) arising from use of `shows' at Expr0.lhs:56:22-26 Probable fix: add (Show a) to the type signature(s) for `showsExpr' In the definition of `showsExpr': showsExpr (Const c) = shows c \end{verbatim} But if we do that, the recursive call is of course still unsatisfied: \begin{verbatim} No instance for (Show a) arising from use of `showsExpr' at Expr0.lhs:65:34-42 Probable fix: add (Show a) to the existential context for `Apply' In the first argument of `(.)', namely `showsExpr a' In the second argument of `(.)', namely `(showsExpr a) . ((')' :))' In the second argument of `(.)', namely `((' ' :)) . ((showsExpr a) . ((')' :)))' \end{verbatim} Following also the advice given in this last error message actually makes GHC accept this, and then we can say: \begin{verbatim} *Expr0> showsExpr e1 "" "(S 41)" *Expr0> showsExpr e2 "" "(isZero (S 41))" \end{verbatim} However, following this advice is counterintuitive and should be unnecessary since the |Show| instance for argument types is only ever used in the const case. We get: \begin{verbatim} *Expr0> showsExpr e3 "" :1:0: No instance for (Show (Int -> Int)) arising from use of `showsExpr' at :1:0-8 Probable fix: add an instance declaration for (Show (Int -> Int)) In the definition of `it': it = showsExpr e3 "" \end{verbatim} But of course we would expect the following: \begin{verbatim} *Expr0> showsExpr e3 "" "(add (S 41))" \end{verbatim} \bigskip The error messages are almost the same if we define a |Show| instance directly (line 90 was the |Const| alternative): \begin{verbatim} Could not deduce (Show a) from the context (Show (Expr a)) arising from use of `shows' at Expr0.lhs:90:26-30 Probable fix: add (Show a) to the class or instance method `showsPrec' \end{verbatim} -}