{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
module Test.StateMachine.Types.References
( Var(Var)
, Symbolic(Symbolic)
, Concrete(Concrete)
, Reference(Reference)
, reference
, concrete
, opaque
, Opaque(Opaque)
, unOpaque
)
where
import Data.Functor.Classes
(Eq1, Ord1, Show1, compare1, eq1, liftCompare,
liftEq, liftShowsPrec, showsPrec1)
import Data.TreeDiff
(Expr(App), ToExpr, toExpr)
import Data.Typeable
(Typeable)
import GHC.Generics
(Generic)
import Prelude
import qualified Test.StateMachine.Types.Rank2 as Rank2
newtype Var = Var Int
deriving (Eq, Ord, Show, Generic, ToExpr)
data Symbolic a where
Symbolic :: Typeable a => Var -> Symbolic a
deriving instance Show (Symbolic a)
deriving instance Eq (Symbolic a)
deriving instance Ord (Symbolic a)
instance Show1 Symbolic where
liftShowsPrec _ _ p (Symbolic x) =
showParen (p > appPrec) $
showString "Symbolic " .
showsPrec (appPrec + 1) x
where
appPrec = 10
instance ToExpr a => ToExpr (Symbolic a) where
toExpr (Symbolic x) = toExpr x
instance Eq1 Symbolic where
liftEq _ (Symbolic x) (Symbolic y) = x == y
instance Ord1 Symbolic where
liftCompare _ (Symbolic x) (Symbolic y) = compare x y
data Concrete a where
Concrete :: Typeable a => a -> Concrete a
deriving instance Show a => Show (Concrete a)
instance Show1 Concrete where
liftShowsPrec sp _ p (Concrete x) =
showParen (p > appPrec) $
showString "Concrete " .
sp (appPrec + 1) x
where
appPrec = 10
instance Eq1 Concrete where
liftEq eq (Concrete x) (Concrete y) = eq x y
instance Ord1 Concrete where
liftCompare comp (Concrete x) (Concrete y) = comp x y
instance ToExpr a => ToExpr (Concrete a) where
toExpr (Concrete x) = toExpr x
data Reference a r = Reference (r a)
deriving Generic
instance ToExpr (r a) => ToExpr (Reference a r)
instance Rank2.Functor (Reference a) where
fmap f (Reference r) = Reference (f r)
instance Rank2.Foldable (Reference a) where
foldMap f (Reference r) = f r
instance Rank2.Traversable (Reference a) where
traverse f (Reference r) = Reference <$> f r
instance (Eq a, Eq1 r) => Eq (Reference a r) where
Reference x == Reference y = eq1 x y
instance (Ord a, Ord1 r) => Ord (Reference a r) where
compare (Reference x) (Reference y) = compare1 x y
instance (Show1 r, Show a) => Show (Reference a r) where
showsPrec p (Reference v) = showParen (p > appPrec) $
showString "Reference " .
showsPrec1 p v
where
appPrec = 10
reference :: Typeable a => a -> Reference a Concrete
reference = Reference . Concrete
concrete :: Reference a Concrete -> a
concrete (Reference (Concrete x)) = x
opaque :: Reference (Opaque a) Concrete -> a
opaque (Reference (Concrete (Opaque x))) = x
newtype Opaque a = Opaque
{ unOpaque :: a }
deriving (Eq, Ord)
instance Show (Opaque a) where
showsPrec _ (Opaque _) = showString "Opaque"
instance ToExpr (Opaque a) where
toExpr _ = App "Opaque" []