summaryrefslogtreecommitdiff
path: root/testsuite/tests/gadt/karl2.hs
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/tests/gadt/karl2.hs')
-rw-r--r--testsuite/tests/gadt/karl2.hs136
1 files changed, 136 insertions, 0 deletions
diff --git a/testsuite/tests/gadt/karl2.hs b/testsuite/tests/gadt/karl2.hs
new file mode 100644
index 0000000000..a701400689
--- /dev/null
+++ b/testsuite/tests/gadt/karl2.hs
@@ -0,0 +1,136 @@
+{-# LANGUAGE GADTs, KindSignatures #-}
+
+module Expr0 where
+
+-- See Trac #301
+-- This one *does* use GADTs (Fct)
+
+data Expr :: * -> * where
+ Const :: Show a => a -> Expr a
+ Apply :: Fct a b -> Expr a -> Expr b
+
+data Fct :: * -> * -> * 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 ""
+
+ <interactive>:1:0:
+ No instance for (Show (Int -> Int))
+ arising from use of `showsExpr' at <interactive>: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}
+-}
+
+