{-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE StandaloneDeriving #-} ----------------------------------------------------------------------------- -- | -- Module : Test.StateMachine.Types.References -- Copyright : (C) 2017, Jacob Stanley -- License : BSD-style (see the file LICENSE) -- -- Maintainer : Stevan Andjelkovic -- Stability : provisional -- Portability : non-portable (GHC extensions) -- -- This module contains reference related types. It's taken almost verbatim from -- the Hedgehog . -- ----------------------------------------------------------------------------- module Test.StateMachine.Types.References ( Reference(..) , concrete , opaque , Opaque(..) , Symbolic(..) , Concrete(..) , Var(..) ) where import Data.Functor.Classes (Eq1(..), Ord1(..), Show1(..), compare1, eq1, showsPrec1) import Data.Typeable (Typeable) import Test.StateMachine.Types.HFunctor ------------------------------------------------------------------------ -- | References are the potential or actual result of executing an action. They -- are parameterised by either `Symbolic` or `Concrete` depending on the -- phase of the test. -- -- `Symbolic` variables are the potential results of actions. These are used -- when generating the sequence of actions to execute. They allow actions -- which occur later in the sequence to make use of the result of an action -- which came earlier in the sequence. -- -- `Concrete` variables are the actual results of actions. These are used -- during test execution. They provide access to the actual runtime value of -- a variable. -- newtype Reference v a = Reference (v a) -- | Take the value from a concrete variable. -- concrete :: Reference Concrete a -> a concrete (Reference (Concrete x)) = x -- | Take the value from an opaque concrete variable. -- opaque :: Reference Concrete (Opaque a) -> a opaque (Reference (Concrete (Opaque x))) = x instance (Eq1 v, Eq a) => Eq (Reference v a) where (==) (Reference x) (Reference y) = eq1 x y instance (Ord1 v, Ord a) => Ord (Reference v a) where compare (Reference x) (Reference y) = compare1 x y instance (Show1 v, Show a) => Show (Reference v a) where showsPrec p (Reference v) = showParen (p > appPrec) $ showString "Reference " . showsPrec1 p v where appPrec = 10 deriving instance Read (v a) => Read (Reference v a) instance HTraversable Reference where htraverse f (Reference v) = fmap Reference (f v) instance HFunctor Reference instance HFoldable Reference ------------------------------------------------------------------------ -- | Opaque values. -- -- Useful if you want to put something without a 'Show' instance inside -- something which you'd like to be able to display. -- newtype Opaque a = Opaque { unOpaque :: a } deriving (Eq, Ord) instance Show (Opaque a) where showsPrec _ (Opaque _) = showString "Opaque" -- | Symbolic variable names. -- newtype Var = Var Int deriving (Eq, Ord, Show, Num, Read) -- | Symbolic values. -- data Symbolic a where Symbolic :: Typeable a => Var -> Symbolic a deriving instance Eq (Symbolic a) deriving instance Ord (Symbolic a) deriving instance Show (Symbolic a) deriving instance Typeable a => Read (Symbolic a) deriving instance Foldable Symbolic instance Eq1 Symbolic where liftEq _ (Symbolic x) (Symbolic y) = x == y instance Ord1 Symbolic where liftCompare _ (Symbolic x) (Symbolic y) = compare x y instance Show1 Symbolic where liftShowsPrec _ _ p (Symbolic x) = showParen (p > appPrec) $ showString "Symbolic " . showsPrec (appPrec + 1) x where appPrec = 10 -- | Concrete values. -- newtype Concrete a where Concrete :: a -> Concrete a deriving (Eq, Ord, Show, Read, Functor, Foldable, Traversable) 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 Show1 Concrete where liftShowsPrec sp _ p (Concrete x) = showParen (p > appPrec) $ showString "Concrete " . sp (appPrec + 1) x where appPrec = 10