{-# LANGUAGE DeriveDataTypeable, FlexibleContexts, StandaloneDeriving, TypeOperators, UndecidableInstances #-}
import Data.Data


infixr 6 :+:
data (f :+: g) e = Inl (f e) | Inr (g e) deriving (Data, Eq)

instance (Functor f, Functor g) => Functor (f :+: g) where
    fmap f (Inl e1) = Inl (fmap f e1)
    fmap f (Inr e2) = Inr (fmap f e2)

instance (Typeable1 f, Typeable1 g) => Typeable1 (f :+: g) where
    typeOf1 l = mkTyConApp (mkTyCon "Planning.Wouter.:+:") [typeOf1 x, typeOf1 y] where
        Inl x = (Inl undefined) `asTypeOf` l
        Inr y = (Inr undefined) `asTypeOf` l



newtype Expr f = In (f (Expr f))
instance Typeable1 f => Typeable (Expr f) where
    typeOf e = mkTyConApp (mkTyCon "Planning.Wouter.Expr") [typeOf1 x]
        where In x = (In undefined) `asTypeOf` e


data Const e = Const String deriving (Data, Eq, Typeable)
data Var e = Var String deriving (Data, Eq, Typeable)

deriving instance (Typeable1 a, Data (a (Expr a))) => Data (Expr a)


data Domain e g = Domain
    (Expr (Const :+: Var))
    deriving (Data, Typeable)

main = return ()
