{-# LANGUAGE NoMonomorphismRestriction, FlexibleInstances, GADTs#-}
-- | This module defines an Obs, which are everything that can be observed by a player'r rules over the state of the game.
module Observable where
import Data.Typeable
type PlayerNumber = Int
type RuleNumber = Int
-- | an Obs allows the player's rule to have access to the state of the game.
-- | it is a compositional algebra defined with a GADT.
data Obs a where
ProposedBy :: Obs PlayerNumber -- The player that proposed the tested rule
RuleNumber :: Obs RuleNumber -- The number of the tested rule
SelfNumber :: Obs RuleNumber -- The number of the testing rule
Official :: Obs Bool -- whereas the tested rule is official
Equ :: (Eq a, Show a, Typeable a) => Obs a -> Obs a -> Obs Bool
Plus :: (Num a) => Obs a -> Obs a -> Obs a
Time :: (Num a) => Obs a -> Obs a -> Obs a
Minus :: (Num a) => Obs a -> Obs a -> Obs a
And :: Obs Bool -> Obs Bool -> Obs Bool
Or :: Obs Bool -> Obs Bool -> Obs Bool
Not :: Obs Bool -> Obs Bool
If :: Obs Bool -> Obs a -> Obs a -> Obs a
Konst :: a -> Obs a
Vote :: Obs String -> Obs Int -> Obs Bool
-- | helpers
oRuleProposedBy = ProposedBy
oRuleNumber = RuleNumber
oRuleOfficial = Official
--oNbPlayer = OpZero "NbPlayer"
oSelfNumber = SelfNumber
oNot = Not
oEqu = Equ
oPlus = Plus
oTime = Time
oMinus = Minus
oAnd = And
oOr = Or
oIf = If
oConst = Konst
oVote = Vote
oListAnd = foldr oAnd (oConst True)
oListOr = foldr oOr (oConst False)
--oEnumFromTo = OpBi "enumFromTo"
instance Bounded a => Bounded (Obs a) where
minBound = Konst $ minBound
maxBound = Konst $ minBound
instance (Num a) => Num (Obs a) where
(+) = oPlus
(*) = oTime
(-) = oMinus
abs = id --TODO correct
signum = const 1
fromInteger = oConst . fromInteger
-- instance Functor (Obs) where
-- fmap f RuleProposedBy = f
--instance Enum Obs where --TODO correct
-- succ a = a + (oConst 1)
-- pred a = a - (oConst 1)
-- toEnum a = (oInt a)
-- fromEnum (OInt a) = a
-- enumFrom (OInt a) = map toEnum [a..]
-- enumFromThen (OInt a) (OInt b) = map toEnum [a, b..]
-- enumFromTo (OInt a) (OInt b) = map toEnum [a..b]
-- enumFromThenTo (OInt a) (OInt b) (OInt c) = map toEnum [a, b..c]
instance Show t => Show (Obs t) where
show ProposedBy = "ProposedBy"
show RuleNumber = "RuleNumber"
show SelfNumber = "SelfNumber"
show Official = "Official"
show (Equ a b) = (show a) ++ " Eq " ++ (show b)
show (Plus a b) = (show a) ++ " Plus " ++ (show b)
show (Minus a b) = (show a) ++ " Minus " ++ (show b)
show (Time a b) = (show a) ++ " Time " ++ (show b)
show (Konst a) = " (Konst " ++ (show a) ++ ")"
show (And a b) = (show a) ++ " And " ++ (show b)
show (Or a b) = (show a) ++ " Or " ++ (show b)
show (Not a) = " (Not " ++ (show a) ++ ")"
show (If a b c) = "If " ++ (show a) ++ " Then " ++ (show b) ++ " Else " ++ (show c)
show (Vote a b) = "Vote " ++ (show a) ++ (show b)
instance Typeable1 Obs where
typeOf1 _ = mkTyConApp (mkTyCon "Obs") []
-- | an equality that tests also the types.
(===) :: (Typeable a, Typeable b, Eq b) => a -> b -> Bool
(===) x y = cast x == Just y
instance Eq t => Eq (Obs t) where
ProposedBy == ProposedBy = True
RuleNumber == RuleNumber = True
SelfNumber == SelfNumber = True
Official == Official = True
Equ a b == Equ c d = (a,b) === (c,d) --i'm obliged to used this === because due to Equ's type, the compiler can't infer that the types of a and c are egual (resp. b and d).
Plus a b == Plus c d = (a,b) == (c,d)
Minus a b == Minus c d = (a,b) == (c,d)
Time a b == Time c d = (a,b) == (c,d)
And a b == And c d = (a,b) == (c,d)
Or a b == Or c d = (a,b) == (c,d)
Not a == Not b = a == b
Konst a == Konst b = a == b
If a b c == If d e f = (a,b,c) == (d,e,f)
Vote a b == Vote c d = (a,b) == (c,d)
_ == _ = False