{-# LANGUAGE GADTs, KindSignatures #-}

-- See #301
-- This particular one doesn't use GADTs per se,
-- but it does use dictionaries in constructors

module Expr1 where

import Data.Kind (Type)

data Expr :: Type -> Type where       -- Not a GADT at all
  Const :: Show a => a -> Expr a
                -- Note the Show constraint here
  Var   :: Var a -> Expr a

newtype Var a = V String

instance Show (Var a) where show (V s) = s

--------------------------
e1 :: Expr Int
e1 = Const 42

e2 :: Expr Bool
e2 = Const True

e3 :: Expr Integer
e3 = Var (V "mersenne100")

--------------------------
eval :: Expr a -> a
eval (Const c) = c
eval (Var v) = error ("free variable `" ++ shows v "'")

{-
    Up to here, everything works nicely:

    \begin{verbatim}
    *Expr0> eval e1
    42
    *Expr0> eval e2
    True
    *Expr1> eval e3
    *** Exception: free variable `mersenne100'
    \end{verbatim}

    But let us now try to define a |shows| function.

    In the following, without the type signature we get:
    \begin{verbatim}
    *Expr1> :t showsExpr
    showsExpr :: forall a. (Show a) => Expr a -> String -> String
    *Expr1> showsExpr e1 ""
    "42"
    *Expr1> showsExpr e2 ""
    "True"
    *Expr1> showsExpr e3 ""
    "mersenne100"
    \end{verbatim}

    However, in the last case, the instance |Show Integer| was not used,
    so should not have been required.
    Therefore I would expect it to work as it is now, i.e.,
    with the type signature:
-}

showsExpr :: Expr a -> ShowS
showsExpr (Const c) = shows c
showsExpr (Var v) = shows v

{-

We used to get a complaint about the |Const| alternative (then line
63) that documents that the constraint in the type of |Const| must
have been ignored:

    No instance for (Show a)
      arising from use of `shows' at Expr1.lhs:63:22-26
    Probable fix: add (Show a) to the type signature(s) for `showsExpr'
    In the definition of `showsExpr': showsExpr (Const c) = shows c
-}
