{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE Safe #-}
module Algebra.Lattice.M2 (
M2 (..),
toSetBool,
fromSetBool,
) where
import Prelude ()
import Prelude.Compat
import Control.DeepSeq (NFData (..))
import Data.Data (Data, Typeable)
import Data.Hashable (Hashable (..))
import Data.Universe.Class (Finite (..), Universe (..))
import GHC.Generics (Generic)
import qualified Test.QuickCheck as QC
import Algebra.Heyting
import Algebra.Lattice
import Algebra.PartialOrd
import Data.Set (Set)
import qualified Data.Set as Set
data M2 = M2o | M2a | M2b | M2i
deriving (Eq, Ord, Read, Show, Enum, Bounded, Typeable, Data, Generic)
instance PartialOrd M2 where
M2o `leq` _ = True
_ `leq` M2i = True
M2a `leq` M2a = True
M2b `leq` M2b = True
_ `leq` _ = False
instance Lattice M2 where
M2o \/ y = y
M2i \/ _ = M2i
x \/ M2o = x
_ \/ M2i = M2i
M2a \/ M2a = M2a
M2b \/ M2b = M2b
_ \/ _ = M2i
M2o /\ _ = M2o
M2i /\ y = y
_ /\ M2o = M2o
x /\ M2i = x
M2a /\ M2a = M2a
M2b /\ M2b = M2b
_ /\ _ = M2o
instance BoundedJoinSemiLattice M2 where
bottom = M2o
instance BoundedMeetSemiLattice M2 where
top = M2i
instance Heyting M2 where
M2o ==> _ = M2i
M2i ==> x = x
M2a ==> M2o = M2b
M2a ==> M2a = M2i
M2a ==> M2b = M2b
M2a ==> M2i = M2i
M2b ==> M2o = M2a
M2b ==> M2a = M2a
M2b ==> M2b = M2i
M2b ==> M2i = M2i
neg M2o = M2i
neg M2a = M2b
neg M2b = M2a
neg M2i = M2o
toSetBool :: M2 -> Set Bool
toSetBool M2o = mempty
toSetBool M2a = Set.singleton False
toSetBool M2b = Set.singleton True
toSetBool M2i = Set.fromList [True, False]
fromSetBool :: Set Bool -> M2
fromSetBool x = case Set.toList x of
[False,True] -> M2i
[False] -> M2a
[True] -> M2b
_ -> M2o
instance QC.Arbitrary M2 where
arbitrary = QC.arbitraryBoundedEnum
shrink x | x == minBound = []
| otherwise = [minBound .. pred x]
instance QC.CoArbitrary M2 where
coarbitrary = QC.coarbitraryEnum
instance QC.Function M2 where
function = QC.functionBoundedEnum
instance Universe M2 where universe = [minBound .. maxBound]
instance Finite M2 where cardinality = 4
instance NFData M2 where
rnf x = x `seq` ()
instance Hashable M2 where
hashWithSalt salt = hashWithSalt salt . fromEnum