{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# 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 stock (Eq, Ord, Show, Generic, Read)
deriving newtype (ToExpr)
data Symbolic a where
Symbolic :: Typeable a => Var -> Symbolic a
deriving stock instance Show (Symbolic a)
deriving stock instance Typeable a => Read (Symbolic a)
deriving stock instance Eq (Symbolic a)
deriving stock 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 stock 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
newtype Reference a r = Reference (r a)
deriving stock Generic
deriving stock instance Typeable a => Read (Reference a Symbolic)
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 stock (Eq, Ord)
instance Show (Opaque a) where
showsPrec _ (Opaque _) = showString "Opaque"
instance ToExpr (Opaque a) where
toExpr _ = App "Opaque" []