{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# OPTIONS_GHC -fno-warn-unused-imports #-}
module Language.Expression.Example where
import Data.Functor.Identity (Identity (..))
import Control.Monad.State
import Data.Map (Map)
import qualified Data.Map as Map
import Data.SBV (EqSymbolic (..), OrdSymbolic (..),
Predicate, SBV, Symbolic, isTheorem,
ite, literal, symbolic)
import Language.Expression
data SimpleOp t a where
Add :: t Integer -> t Integer -> SimpleOp t Integer
Equal :: t Integer -> t Integer -> SimpleOp t Bool
IfThenElse :: t Bool -> t Integer -> t Integer -> SimpleOp t Integer
Literal :: Integer -> SimpleOp t Integer
instance HFunctor SimpleOp
instance HTraversable SimpleOp where
htraverse :: (forall b. t b -> f (t' b)) -> SimpleOp t a -> f (SimpleOp t' a)
htraverse forall b. t b -> f (t' b)
f = \case
Add t Integer
x t Integer
y -> t' Integer -> t' Integer -> SimpleOp t' Integer
forall (t :: * -> *). t Integer -> t Integer -> SimpleOp t Integer
Add (t' Integer -> t' Integer -> SimpleOp t' Integer)
-> f (t' Integer) -> f (t' Integer -> SimpleOp t' Integer)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> t Integer -> f (t' Integer)
forall b. t b -> f (t' b)
f t Integer
x f (t' Integer -> SimpleOp t' Integer)
-> f (t' Integer) -> f (SimpleOp t' Integer)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> t Integer -> f (t' Integer)
forall b. t b -> f (t' b)
f t Integer
y
Equal t Integer
x t Integer
y -> t' Integer -> t' Integer -> SimpleOp t' Bool
forall (t :: * -> *). t Integer -> t Integer -> SimpleOp t Bool
Equal (t' Integer -> t' Integer -> SimpleOp t' Bool)
-> f (t' Integer) -> f (t' Integer -> SimpleOp t' Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> t Integer -> f (t' Integer)
forall b. t b -> f (t' b)
f t Integer
x f (t' Integer -> SimpleOp t' Bool)
-> f (t' Integer) -> f (SimpleOp t' Bool)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> t Integer -> f (t' Integer)
forall b. t b -> f (t' b)
f t Integer
y
IfThenElse t Bool
x t Integer
y t Integer
z -> t' Bool -> t' Integer -> t' Integer -> SimpleOp t' Integer
forall (t :: * -> *).
t Bool -> t Integer -> t Integer -> SimpleOp t Integer
IfThenElse (t' Bool -> t' Integer -> t' Integer -> SimpleOp t' Integer)
-> f (t' Bool)
-> f (t' Integer -> t' Integer -> SimpleOp t' Integer)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> t Bool -> f (t' Bool)
forall b. t b -> f (t' b)
f t Bool
x f (t' Integer -> t' Integer -> SimpleOp t' Integer)
-> f (t' Integer) -> f (t' Integer -> SimpleOp t' Integer)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> t Integer -> f (t' Integer)
forall b. t b -> f (t' b)
f t Integer
y f (t' Integer -> SimpleOp t' Integer)
-> f (t' Integer) -> f (SimpleOp t' Integer)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> t Integer -> f (t' Integer)
forall b. t b -> f (t' b)
f t Integer
z
Literal Integer
x -> SimpleOp t' Integer -> f (SimpleOp t' Integer)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Integer -> SimpleOp t' Integer
forall (t :: * -> *). Integer -> SimpleOp t Integer
Literal Integer
x)
data SimpleVar a where
SimpleVar :: String -> SimpleVar Integer
type SimpleExpr = HFree SimpleOp SimpleVar
var :: String -> SimpleExpr Integer
var :: String -> SimpleExpr Integer
var = SimpleVar Integer -> SimpleExpr Integer
forall k (h :: (k -> *) -> k -> *) (t :: k -> *) (a :: k).
HPointed h =>
t a -> h t a
hpure (SimpleVar Integer -> SimpleExpr Integer)
-> (String -> SimpleVar Integer) -> String -> SimpleExpr Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> SimpleVar Integer
SimpleVar
(^+) :: SimpleExpr Integer -> SimpleExpr Integer -> SimpleExpr Integer
SimpleExpr Integer
x ^+ :: SimpleExpr Integer -> SimpleExpr Integer -> SimpleExpr Integer
^+ SimpleExpr Integer
y = SimpleOp (HFree SimpleOp SimpleVar) Integer -> SimpleExpr Integer
forall k (h :: (k -> *) -> k -> *) (t :: k -> *) (a :: k).
h (HFree h t) a -> HFree h t a
HWrap (SimpleExpr Integer
-> SimpleExpr Integer
-> SimpleOp (HFree SimpleOp SimpleVar) Integer
forall (t :: * -> *). t Integer -> t Integer -> SimpleOp t Integer
Add SimpleExpr Integer
x SimpleExpr Integer
y)
(^==) :: SimpleExpr Integer -> SimpleExpr Integer -> SimpleExpr Bool
SimpleExpr Integer
x ^== :: SimpleExpr Integer -> SimpleExpr Integer -> SimpleExpr Bool
^== SimpleExpr Integer
y = SimpleOp (HFree SimpleOp SimpleVar) Bool -> SimpleExpr Bool
forall k (h :: (k -> *) -> k -> *) (t :: k -> *) (a :: k).
h (HFree h t) a -> HFree h t a
HWrap (SimpleExpr Integer
-> SimpleExpr Integer -> SimpleOp (HFree SimpleOp SimpleVar) Bool
forall (t :: * -> *). t Integer -> t Integer -> SimpleOp t Bool
Equal SimpleExpr Integer
x SimpleExpr Integer
y)
ifThenElse :: SimpleExpr Bool -> SimpleExpr Integer -> SimpleExpr Integer -> SimpleExpr Integer
ifThenElse :: SimpleExpr Bool
-> SimpleExpr Integer -> SimpleExpr Integer -> SimpleExpr Integer
ifThenElse SimpleExpr Bool
x SimpleExpr Integer
y SimpleExpr Integer
z = SimpleOp (HFree SimpleOp SimpleVar) Integer -> SimpleExpr Integer
forall k (h :: (k -> *) -> k -> *) (t :: k -> *) (a :: k).
h (HFree h t) a -> HFree h t a
HWrap (SimpleExpr Bool
-> SimpleExpr Integer
-> SimpleExpr Integer
-> SimpleOp (HFree SimpleOp SimpleVar) Integer
forall (t :: * -> *).
t Bool -> t Integer -> t Integer -> SimpleOp t Integer
IfThenElse SimpleExpr Bool
x SimpleExpr Integer
y SimpleExpr Integer
z)
lit :: Integer -> SimpleExpr Integer
lit :: Integer -> SimpleExpr Integer
lit = SimpleOp (HFree SimpleOp SimpleVar) Integer -> SimpleExpr Integer
forall k (h :: (k -> *) -> k -> *) (t :: k -> *) (a :: k).
h (HFree h t) a -> HFree h t a
HWrap (SimpleOp (HFree SimpleOp SimpleVar) Integer -> SimpleExpr Integer)
-> (Integer -> SimpleOp (HFree SimpleOp SimpleVar) Integer)
-> Integer
-> SimpleExpr Integer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> SimpleOp (HFree SimpleOp SimpleVar) Integer
forall (t :: * -> *). Integer -> SimpleOp t Integer
Literal
exampleExpr :: SimpleExpr Integer
exampleExpr :: SimpleExpr Integer
exampleExpr = SimpleExpr Bool
-> SimpleExpr Integer -> SimpleExpr Integer -> SimpleExpr Integer
ifThenElse (String -> SimpleExpr Integer
var String
"x" SimpleExpr Integer -> SimpleExpr Integer -> SimpleExpr Bool
^== Integer -> SimpleExpr Integer
lit Integer
10) (String -> SimpleExpr Integer
var String
"y") (String -> SimpleExpr Integer
var String
"y" SimpleExpr Integer -> SimpleExpr Integer -> SimpleExpr Integer
^+ Integer -> SimpleExpr Integer
lit Integer
5)
exampleExpr2 :: SimpleExpr Integer
exampleExpr2 :: SimpleExpr Integer
exampleExpr2 =
SimpleExpr Integer
exampleExpr SimpleExpr Integer
-> (forall b. SimpleVar b -> HFree SimpleOp SimpleVar b)
-> SimpleExpr Integer
forall k (h :: (k -> *) -> k -> *) (t :: k -> *) (a :: k)
(t' :: k -> *).
HBind h =>
h t a -> (forall (b :: k). t b -> h t' b) -> h t' a
^>>= \v :: SimpleVar b
v@(SimpleVar String
nm) ->
if String
nm String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
"x" then String -> SimpleExpr Integer
var String
"z" SimpleExpr Integer -> SimpleExpr Integer -> SimpleExpr Integer
^+ Integer -> SimpleExpr Integer
lit Integer
5 else SimpleVar b -> HFree SimpleOp SimpleVar b
forall k (h :: (k -> *) -> k -> *) (t :: k -> *) (a :: k).
HPointed h =>
t a -> h t a
hpure SimpleVar b
v
evalXOrY :: SimpleVar a -> Maybe (Identity a)
evalXOrY :: SimpleVar a -> Maybe (Identity a)
evalXOrY (SimpleVar String
"x") = Identity a -> Maybe (Identity a)
forall a. a -> Maybe a
Just (a -> Identity a
forall a. a -> Identity a
Identity a
1)
evalXOrY (SimpleVar String
"y") = Identity a -> Maybe (Identity a)
forall a. a -> Maybe a
Just (a -> Identity a
forall a. a -> Identity a
Identity a
2)
evalXOrY SimpleVar a
_ = Maybe (Identity a)
forall a. Maybe a
Nothing
instance HFoldableAt Identity SimpleOp where
hfoldMap :: (forall b. t b -> Identity b) -> SimpleOp t a -> Identity a
hfoldMap forall b. t b -> Identity b
f SimpleOp t a
s = case SimpleOp t a
s of
Add t Integer
x t Integer
y -> Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
(+) (Integer -> Integer -> Integer)
-> Identity Integer -> Identity (Integer -> Integer)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> t Integer -> Identity Integer
forall b. t b -> Identity b
f t Integer
x Identity (Integer -> Integer)
-> Identity Integer -> Identity Integer
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> t Integer -> Identity Integer
forall b. t b -> Identity b
f t Integer
y
Equal t Integer
x t Integer
y -> Integer -> Integer -> Bool
forall a. Eq a => a -> a -> Bool
(==) (Integer -> Integer -> Bool)
-> Identity Integer -> Identity (Integer -> Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> t Integer -> Identity Integer
forall b. t b -> Identity b
f t Integer
x Identity (Integer -> Bool) -> Identity Integer -> Identity Bool
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> t Integer -> Identity Integer
forall b. t b -> Identity b
f t Integer
y
IfThenElse t Bool
x t Integer
y t Integer
z ->
let ite' :: Bool -> p -> p -> p
ite' Bool
c p
a p
b = if Bool
c then p
a else p
b
in Bool -> Integer -> Integer -> Integer
forall p. Bool -> p -> p -> p
ite' (Bool -> Integer -> Integer -> Integer)
-> Identity Bool -> Identity (Integer -> Integer -> Integer)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> t Bool -> Identity Bool
forall b. t b -> Identity b
f t Bool
x Identity (Integer -> Integer -> Integer)
-> Identity Integer -> Identity (Integer -> Integer)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> t Integer -> Identity Integer
forall b. t b -> Identity b
f t Integer
y Identity (Integer -> Integer)
-> Identity Integer -> Identity Integer
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> t Integer -> Identity Integer
forall b. t b -> Identity b
f t Integer
z
Literal Integer
x -> Integer -> Identity Integer
forall (f :: * -> *) a. Applicative f => a -> f a
pure Integer
x
evalVarSymbolic :: SimpleVar a -> StateT (Map String (SBV Integer)) Symbolic (SBV a)
evalVarSymbolic :: SimpleVar a -> StateT (Map String (SBV Integer)) Symbolic (SBV a)
evalVarSymbolic (SimpleVar String
nm) = do
Maybe (SBV a)
existingSymbol <- (Map String (SBV a) -> Maybe (SBV a))
-> StateT (Map String (SBV Integer)) Symbolic (Maybe (SBV a))
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets (String -> Map String (SBV a) -> Maybe (SBV a)
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
nm)
case Maybe (SBV a)
existingSymbol of
Just SBV a
x -> SBV a -> StateT (Map String (SBV Integer)) Symbolic (SBV a)
forall (m :: * -> *) a. Monad m => a -> m a
return SBV a
x
Maybe (SBV a)
Nothing -> do
SBV a
newSymbol <- SymbolicT IO (SBV a)
-> StateT (Map String (SBV Integer)) Symbolic (SBV a)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (String -> SymbolicT IO (SBV a)
forall a. SymVal a => String -> Symbolic (SBV a)
symbolic String
nm)
(Map String (SBV a) -> Map String (SBV a))
-> StateT (Map String (SBV Integer)) Symbolic ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify (String -> SBV a -> Map String (SBV a) -> Map String (SBV a)
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert String
nm SBV a
newSymbol)
SBV a -> StateT (Map String (SBV Integer)) Symbolic (SBV a)
forall (m :: * -> *) a. Monad m => a -> m a
return SBV a
newSymbol
instance HFoldableAt SBV SimpleOp where
hfoldMap :: (forall b. t b -> SBV b) -> SimpleOp t a -> SBV a
hfoldMap = (SimpleOp SBV a -> SBV a)
-> (forall b. t b -> SBV b) -> SimpleOp t a -> SBV a
forall u (h :: (u -> *) -> u -> *) (k :: u -> *) (a :: u)
(t :: u -> *).
HFunctor h =>
(h k a -> k a) -> (forall (b :: u). t b -> k b) -> h t a -> k a
implHfoldMap ((SimpleOp SBV a -> SBV a)
-> (forall b. t b -> SBV b) -> SimpleOp t a -> SBV a)
-> (SimpleOp SBV a -> SBV a)
-> (forall b. t b -> SBV b)
-> SimpleOp t a
-> SBV a
forall a b. (a -> b) -> a -> b
$ \SimpleOp SBV a
s -> case SimpleOp SBV a
s of
Add SBV Integer
x SBV Integer
y -> SBV Integer
x SBV Integer -> SBV Integer -> SBV Integer
forall a. Num a => a -> a -> a
+ SBV Integer
y
Equal SBV Integer
x SBV Integer
y -> SBV Integer
x SBV Integer -> SBV Integer -> SBool
forall a. EqSymbolic a => a -> a -> SBool
.== SBV Integer
y
IfThenElse SBool
x SBV Integer
y SBV Integer
z -> SBool -> SBV Integer -> SBV Integer -> SBV Integer
forall a. Mergeable a => SBool -> a -> a -> a
ite SBool
x SBV Integer
y SBV Integer
z
Literal Integer
x -> Integer -> SBV Integer
forall a. SymVal a => a -> SBV a
literal Integer
x
evalSimpleExprSymbolic :: SimpleExpr a -> StateT (Map String (SBV Integer)) Symbolic (SBV a)
evalSimpleExprSymbolic :: SimpleExpr a -> StateT (Map String (SBV Integer)) Symbolic (SBV a)
evalSimpleExprSymbolic = (forall b.
SimpleVar b -> StateT (Map String (SBV Integer)) Symbolic (SBV b))
-> SimpleExpr a
-> StateT (Map String (SBV Integer)) Symbolic (SBV a)
forall u (k :: u -> *) (h :: (u -> *) -> u -> *) (f :: * -> *)
(t :: u -> *) (a :: u).
(HFoldableAt k h, HTraversable h, Applicative f) =>
(forall (b :: u). t b -> f (k b)) -> h t a -> f (k a)
hfoldTraverse forall b.
SimpleVar b -> StateT (Map String (SBV Integer)) Symbolic (SBV b)
evalVarSymbolic
examplePredicate :: Predicate
examplePredicate :: Predicate
examplePredicate = (StateT (Map String (SBV Integer)) Symbolic SBool
-> Map String (SBV Integer) -> Predicate)
-> Map String (SBV Integer)
-> StateT (Map String (SBV Integer)) Symbolic SBool
-> Predicate
forall a b c. (a -> b -> c) -> b -> a -> c
flip StateT (Map String (SBV Integer)) Symbolic SBool
-> Map String (SBV Integer) -> Predicate
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m a
evalStateT Map String (SBV Integer)
forall a. Monoid a => a
mempty (StateT (Map String (SBV Integer)) Symbolic SBool -> Predicate)
-> StateT (Map String (SBV Integer)) Symbolic SBool -> Predicate
forall a b. (a -> b) -> a -> b
$ do
SBV Integer
expr <- SimpleExpr Integer
-> StateT (Map String (SBV Integer)) Symbolic (SBV Integer)
forall a.
SimpleExpr a -> StateT (Map String (SBV Integer)) Symbolic (SBV a)
evalSimpleExprSymbolic SimpleExpr Integer
exampleExpr
SBV Integer
y <- SimpleExpr Integer
-> StateT (Map String (SBV Integer)) Symbolic (SBV Integer)
forall a.
SimpleExpr a -> StateT (Map String (SBV Integer)) Symbolic (SBV a)
evalSimpleExprSymbolic (String -> SimpleExpr Integer
var String
"y")
SBool -> StateT (Map String (SBV Integer)) Symbolic SBool
forall (m :: * -> *) a. Monad m => a -> m a
return (SBV Integer
expr SBV Integer -> SBV Integer -> SBool
forall a. OrdSymbolic a => a -> a -> SBool
.>= SBV Integer
y)