{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
module Data.Expr.Sugar (
(@+), (@-), (@*), (@/), (@%), (@?), (@??), (@:),
(!), (@!!), (@++), (@..), size, slice, xhead, xtail, xmap, xfold, list, channel, xsum,
(@||), (@&&), inv,
(@/=), (@>), (@<), (@>=), (@<=), (@=),
loopall, loopany, forall, forany,
Expr(), ColExpr(), BoolExpr(),
ToExpr(..), ToColExpr(..), ToBoolExpr(..),
sorted, sSorted, allDiff, allDiffD,
ExprClass, ExprRange,
) where
import Data.Expr.Data
import Data.Expr.Util
instance (Eq s, Eq c, Eq b, Show s, Show c, Show b) => Num (Expr s c b) where
a + b = simplify $ a `Plus` b
a - b = simplify $ a `Minus` b
a * b = simplify $ a `Mult` b
abs a = simplify $ Abs a
negate a = simplify $ (Const 0) `Minus` a
fromInteger c = Const $ fromInteger c
signum (Const a) = Const $ signum a
signum a = error "signum not possible for generic Expr"
instance (Ord s, Ord c, Ord b, Eq s, Eq c, Eq b, Show s, Show c, Show b) => Real (Expr s c b) where
toRational (Const x) = toRational x
toRational _ = error "toRational not possible for generic Expr"
instance (Eq s, Eq c, Eq b) => Enum (Expr s c b) where
succ a = simplify $ a `Plus` (Const 1)
pred a = simplify $ a `Minus` (Const 1)
toEnum = Const . toEnum
fromEnum (Const a) = fromEnum a
fromEnum _ = error "fromEnum not possible for generic Expr"
instance (Ord s, Ord c, Ord b, Eq s, Eq c, Eq b, Show s, Show c, Show b) => Integral (Expr s c b) where
toInteger (Const a) = toInteger a
toInteger _ = error "toInteger not possible for generic Expr"
divMod a b = (simplify $ a `Div` b, simplify $ a `Mod` b)
quotRem (Const a) (Const b) = case quotRem a b of (c,d) -> (Const c,Const d)
quotRem (Const 0) b = (Const 0,Const 0)
quotRem a (Const 1) = (a,Const 0)
quotRem a (Const (-1)) = (negate a,Const 0)
quotRem _ _ = error "quotRem not possible for generic Expr"
class ToExpr tt cc bb t where
toExpr :: t -> Expr tt cc bb
class ToColExpr tt cc bb c where
toColExpr :: c -> ColExpr tt cc bb
class ToBoolExpr tt cc bb b where
toBoolExpr :: b -> BoolExpr tt cc bb
class (Eq tt, Eq cc, Eq bb) => ExprClass tt cc bb a where
(@=) :: a -> a -> BoolExpr tt cc bb
(@/=) :: a -> a -> BoolExpr tt cc bb
a @/= b = boolSimplify $ BoolNot $ a @= b
class (Eq tt, Eq cc, Eq bb) => ExprRange tt cc bb r where
(@:) :: Expr tt cc bb -> r -> BoolExpr tt cc bb
instance ToExpr tt cc bb Integer where
toExpr = Const
instance ToExpr t a b (Expr t a b) where
toExpr = id
instance ToExpr tt cc bb Int where
toExpr = Const . toInteger
instance (Eq t, Eq a, Eq b) => ToExpr t a b (BoolExpr t a b) where
toExpr = simplify . Channel
instance ToColExpr t a b (ColExpr t a b) where
toColExpr = id
instance (Eq t, Eq a, Eq b) => ToColExpr t a b (Expr t a b) where
toColExpr a = colSimplify $ ColList [a]
instance (Eq b, Eq a, Eq t) => ToColExpr t a b [Expr t a b] where
toColExpr = colSimplify . ColList
instance ToBoolExpr tt cc bb Bool where
toBoolExpr = BoolConst
instance ToBoolExpr t a b (BoolExpr t a b) where
toBoolExpr = id
instance ToExpr t a b t where
toExpr = Term
instance ToColExpr t a b a where
toColExpr = ColTerm
instance ToBoolExpr t a b b where
toBoolExpr = BoolTerm
infixl 6 @+, @-
infixl 7 @*
infixl 7 @/
infixl 7 @%
(@+) :: (Eq t, Eq c, Eq b, ToExpr t c b p, ToExpr t c b q) => p -> q -> Expr t c b
(@-) :: (Eq t, Eq c, Eq b, ToExpr t c b p, ToExpr t c b q) => p -> q -> Expr t c b
(@*) :: (Eq t, Eq c, Eq b, ToExpr t c b p, ToExpr t c b q) => p -> q -> Expr t c b
(@/) :: (Eq t, Eq c, Eq b, ToExpr t c b p, ToExpr t c b q) => p -> q -> Expr t c b
(@%) :: (Eq t, Eq c, Eq b, ToExpr t c b p, ToExpr t c b q) => p -> q -> Expr t c b
a @+ b = simplify $ (toExpr a) `Plus` (toExpr b)
a @- b = simplify $ (toExpr a) `Minus` (toExpr b)
a @* b = simplify $ (toExpr a) `Mult` (toExpr b)
a @/ b = simplify $ (toExpr a) `Div` (toExpr b)
a @% b = simplify $ (toExpr a) `Mod` (toExpr b)
infix 9 !
infix 9 @!!
infix 9 @..
infixr 5 @++
infix 4 @?
infix 4 @??
infix 5 @:
(!) :: (Eq t, Eq c, Eq b) => ColExpr t c b -> Expr t c b -> Expr t c b
(@!!) :: (Eq t, Eq c, Eq b) => ColExpr t c b -> Integer -> Expr t c b
(@..) :: (Eq t, Eq c, Eq b) => Expr t c b -> Expr t c b -> ColExpr t c b
(@++) :: (Eq t, Eq c, Eq b) => ColExpr t c b -> ColExpr t c b -> ColExpr t c b
(@?) :: (Eq t, Eq c, Eq b) => BoolExpr t c b -> (Expr t c b, Expr t c b) -> Expr t c b
c @? (t,f) = simplify $ Cond c t f
(@??) :: (Eq t, Eq c, Eq b) => BoolExpr t c b -> (BoolExpr t c b, BoolExpr t c b) -> BoolExpr t c b
c @?? (t,f) = boolSimplify $ BoolCond c t f
c!p = simplify $ At c p
c @!! p = simplify $ At c (Const p)
a @.. b = colSimplify $ ColRange (toExpr a) (toExpr b)
a @++ b = colSimplify $ ColCat (toColExpr a) (toColExpr b)
size :: (Eq t, Eq c, Eq b) => ColExpr t c b -> Expr t c b
size a = simplify $ ColSize a
xfold :: (Eq t, Eq c, Eq b) => (Expr t c b -> Expr t c b -> Expr t c b) -> Expr t c b -> ColExpr t c b -> Expr t c b
xfold f i c = simplify $ Fold (\a b -> f a b) i c
xsum :: (Num (Expr t c b), Eq t, Eq c, Eq b) => ColExpr t c b -> Expr t c b
xsum c = xfold (+) (Const 0) c
list :: (Eq t, Eq c, Eq b) => [Expr t c b] -> ColExpr t c b
list x = colSimplify $ ColList x
xhead :: (Eq t, Eq c, Eq b, ToColExpr t c b p) => p -> Expr t c b
xhead c = simplify $ At (toColExpr c) (Const 0)
xtail :: (Eq t, Eq c, Eq b, ToColExpr t c b p) => p -> ColExpr t c b
xtail c = let cc = toColExpr c in colSimplify $ ColSlice (\x -> simplify (x `Plus` (Const 1))) (simplify $ (size cc) `Minus` (Const 1)) cc
slice :: (Eq t, Eq c, Eq b) => ColExpr t c b -> ColExpr t c b -> ColExpr t c b
slice c p = case (c,p) of
(_,ColRange l h) -> colSimplify $ ColSlice (\x -> simplify (l `Plus` x)) (simplify $ Const 1 `Plus` (simplify $ h `Minus` l)) c
(_,ColMap f (ColRange l h)) -> colSimplify $ ColSlice (\i -> simplify $ f $ simplify (l `Plus` i)) (simplify $ Const 1 `Plus` (simplify $ h `Minus` l)) c
(_,ColSlice f n c2) -> colSimplify $ ColSlice (\i -> simplify $ c2 `At` (f i)) n c
_ -> xmap (\i -> simplify $ c `At` i) p
xmap :: (Eq t, Eq c, Eq b) => (Expr t c b -> Expr t c b) -> ColExpr t c b -> ColExpr t c b
xmap f c = colSimplify $ ColMap f c
loopall :: (Eq t, Eq c, Eq b) => (Expr t c b,Expr t c b) -> (Expr t c b -> BoolExpr t c b) -> BoolExpr t c b
loopall (l,h) f = boolSimplify $ BoolAll f $ colSimplify $ ColRange l h
loopany :: (Eq t, Eq c, Eq b) => (Expr t c b,Expr t c b) -> (Expr t c b -> BoolExpr t c b) -> BoolExpr t c b
loopany (l,h) f = boolSimplify $ BoolAny f $ colSimplify $ ColRange l h
forall :: (Eq t, Eq c, Eq b) => (ColExpr t c b) -> (Expr t c b -> BoolExpr t c b) -> BoolExpr t c b
forall c f = boolSimplify $ BoolAll f c
forany :: (Eq t, Eq c, Eq b) => (ColExpr t c b) -> (Expr t c b -> BoolExpr t c b) -> BoolExpr t c b
forany c f = boolSimplify $ BoolAny f c
channel :: (Eq t, Eq c, Eq b) => BoolExpr t c b -> Expr t c b
channel = simplify . Channel
infixr 2 @||
infixr 3 @&&
inv :: (Eq t, Eq c, Eq b, ToBoolExpr t c b p) => p -> BoolExpr t c b
a @|| b = boolSimplify $ BoolOr (toBoolExpr a) (toBoolExpr b)
a @&& b = boolSimplify $ BoolAnd (toBoolExpr a) (toBoolExpr b)
inv a = boolSimplify $ BoolNot (toBoolExpr a)
instance (Eq t, Eq c, Eq b) => ExprClass t c b (Expr t c b) where
a @= b = boolSimplify $ Rel a EREqual b
instance (Eq t, Eq c, Eq b) => ExprClass t c b (BoolExpr t c b) where
a @= b = boolSimplify $ BoolEqual a b
instance (Eq t, Eq c, Eq b) => ExprClass t c b (ColExpr t c b) where
a @= b = boolSimplify $ ColEqual a b
infixr 4 @<,@<=,@>,@>=
(@<) :: (Eq t, Eq c, Eq b) => Expr t c b -> Expr t c b -> BoolExpr t c b
(@>) :: (Eq t, Eq c, Eq b) => Expr t c b -> Expr t c b -> BoolExpr t c b
(@<=) :: (Eq t, Eq c, Eq b) => Expr t c b -> Expr t c b -> BoolExpr t c b
(@>=) :: (Eq t, Eq c, Eq b) => Expr t c b -> Expr t c b -> BoolExpr t c b
a @< b = boolSimplify $ Rel a ERLess b
a @> b = boolSimplify $ Rel b ERLess a
a @<= b = boolSimplify $ Rel a ERLess (simplify $ b `Plus` (Const 1))
a @>= b = boolSimplify $ Rel b ERLess (simplify $ a `Plus` (Const 1))
sorted c = boolSimplify $ Sorted False c
sSorted c = boolSimplify $ Sorted True c
allDiff c = boolSimplify $ AllDiff False c
allDiffD c = boolSimplify $ AllDiff True c
instance (Eq t, Eq c, Eq b) => ExprRange t c b (Expr t c b,Expr t c b) where
a @: (l,h) = (a @>= l) @&& (a @<= h)
instance (Eq t, Eq c, Eq b) => ExprRange t c b (ColExpr t c b) where
a @: c = boolSimplify $ Dom a c