grisette-0.8.0.0: Symbolic evaluation as a library
Copyright(c) Sirui Lu 2021-2024
LicenseBSD-3-Clause (see the LICENSE file)
Maintainersiruilu@cs.washington.edu
StabilityExperimental
PortabilityGHC only
Safe HaskellTrustworthy
LanguageHaskell2010

Grisette.Internal.Core.Control.Monad.Union

Description

 
Synopsis

Union and helpers

data Union a where Source #

Union is the UnionBase container (hidden) enhanced with MergingStrategy knowledge propagation.

The UnionBase models the underlying semantics evaluation semantics for unsolvable types with the nested if-then-else tree semantics, and can be viewed as the following structure:

data UnionBase a
  = UnionSingle a
  | UnionIf bool (Union a) (Union a)

The UnionSingle constructor is for a single value with the path condition true, and the UnionIf constructor is the if operator in an if-then-else tree. For clarity, when printing a Union value, we will omit the UnionSingle constructor. The following two representations has the same semantics.

If      c1    (If c11 v11 (If c12 v12 v13))
  (If   c2    v2
              v3)

\[ \left\{\begin{aligned}&t_1&&\mathrm{if}&&c_1\\&v_2&&\mathrm{else if}&&c_2\\&v_3&&\mathrm{otherwise}&&\end{aligned}\right.\hspace{2em}\mathrm{where}\hspace{2em}t_1 = \left\{\begin{aligned}&v_{11}&&\mathrm{if}&&c_{11}\\&v_{12}&&\mathrm{else if}&&c_{12}\\&v_{13}&&\mathrm{otherwise}&&\end{aligned}\right. \]

To reduce the size of the if-then-else tree to reduce the number of paths to execute, Grisette would merge the branches in a UnionBase container and maintain a representation invariant for them. To perform this merging procedure, Grisette relies on a type class called Mergeable and the merging strategy defined by it.

UnionBase is a monad, so we can easily write code with the do-notation and monadic combinators. However, the standard monadic operators cannot resolve any extra constraints, including the Mergeable constraint (see The constrained-monad problem by Sculthorpe et al.). This prevents the standard do-notations to merge the results automatically, and would result in bad performance or very verbose code.

To reduce this boilerplate, Grisette provide another monad, Union that would try to cache the merging strategy. The Union has two data constructors (hidden intentionally), UAny and UMrg. The UAny data constructor (printed as <...>) wraps an arbitrary (probably unmerged) UnionBase. It is constructed when no Mergeable knowledge is available (for example, when constructed with Haskell's return). The UMrg data constructor (printed as {...}) wraps a merged UnionBase along with the Mergeable constraint. This constraint can be propagated to the contexts without Mergeable knowledge, and helps the system to merge the resulting UnionBase.

Examples:

return cannot resolve the Mergeable constraint.

>>> return 1 :: Union Integer
<1>

mrgReturn can resolve the Mergeable constraint.

>>> import Grisette.Lib.Base
>>> mrgReturn 1 :: Union Integer
{1}

mrgIfPropagatedStrategy does not try to Mergeable constraint.

>>> mrgIfPropagatedStrategy "a" (return 1) (mrgIfPropagatedStrategy "b" (return 1) (return 2)) :: Union Integer
<If a 1 (If b 1 2)>

But mrgIfPropagatedStrategy is able to merge the result if some of the branches are merged and have a cached merging strategy:

>>> mrgIfPropagatedStrategy "a" (return 1) (mrgIfPropagatedStrategy "b" (mrgReturn 1) (return 2)) :: Union Integer
{If (|| a b) 1 2}

The >>= operator uses mrgIfPropagatedStrategy internally. When the final statement in a do-block merges the values, the system can then merge the final result.

>>> :{
  do
    x <- mrgIfPropagatedStrategy (ssym "a") (return 1) (mrgIfPropagatedStrategy (ssym "b") (return 1) (return 2))
    mrgSingle $ x + 1 :: Union Integer
:}
{If (|| a b) 2 3}

Calling a function that merges a result at the last line of a do-notation will also merge the whole block. If you stick to these mrg* combinators and all the functions will merge the results, the whole program can be symbolically evaluated efficiently.

>>> f x y = mrgIf "c" x y :: Union Integer
>>> :{
  do
    x <- mrgIfPropagatedStrategy (ssym "a") (return 1) (mrgIfPropagatedStrategy (ssym "b") (return 1) (return 2))
    f x (x + 1)
:}
{If (&& c (|| a b)) 1 (If (|| a (|| b c)) 2 3)}

In Grisette.Lib.Base, Grisette.Lib.Mtl, we also provided more mrg* variants of other combinators. You should stick to these combinators to ensure efficient merging by Grisette.

Constructors

UAny

Union with no Mergeable knowledge.

Fields

UMrg

Union with Mergeable knowledge.

Fields

Instances

Instances details
Eq1 Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

liftEq :: (a -> b -> Bool) -> Union a -> Union b -> Bool #

Show1 Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

liftShowsPrec :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> Int -> Union a -> ShowS #

liftShowList :: (Int -> a -> ShowS) -> ([a] -> ShowS) -> [Union a] -> ShowS #

Applicative Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

pure :: a -> Union a #

(<*>) :: Union (a -> b) -> Union a -> Union b #

liftA2 :: (a -> b -> c) -> Union a -> Union b -> Union c #

(*>) :: Union a -> Union b -> Union b #

(<*) :: Union a -> Union b -> Union a #

Functor Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

fmap :: (a -> b) -> Union a -> Union b #

(<$) :: a -> Union b -> Union a #

Monad Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

(>>=) :: Union a -> (a -> Union b) -> Union b #

(>>) :: Union a -> Union b -> Union b #

return :: a -> Union a #

NFData1 Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

liftRnf :: (a -> ()) -> Union a -> () #

MonadParallelUnion Union Source # 
Instance details

Defined in Grisette.Experimental.MonadParallelUnion

Methods

parBindUnion :: (Mergeable b, NFData b) => Union a -> (a -> Union b) -> Union b Source #

EvalSym1 Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

liftEvalSym :: (Bool -> Model -> a -> a) -> Bool -> Model -> Union a -> Union a Source #

ExtractSym1 Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

liftExtractSymMaybe :: forall (knd :: SymbolKind) a. IsSymbolKind knd => (a -> Maybe (SymbolSet knd)) -> Union a -> Maybe (SymbolSet knd) Source #

Mergeable1 Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

PPrint1 Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

liftPFormatPrec :: (Int -> a -> Doc ann) -> ([a] -> Doc ann) -> Int -> Union a -> Doc ann Source #

liftPFormatList :: (Int -> a -> Doc ann) -> ([a] -> Doc ann) -> [Union a] -> Doc ann Source #

PlainUnion Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

SimpleMergeable1 Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

liftMrgIte :: (SymBool -> a -> a -> a) -> SymBool -> Union a -> Union a -> Union a Source #

SymBranching Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

SubstSym1 Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

liftSubstSym :: forall cb sb (knd :: SymbolKind) a. (LinkedRep cb sb, IsSymbolKind knd) => (TypedSymbol knd cb -> sb -> a -> a) -> TypedSymbol knd cb -> sb -> Union a -> Union a Source #

SymEq1 Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

liftSymEq :: (a -> b -> SymBool) -> Union a -> Union b -> SymBool Source #

SymOrd1 Union Source # 
Instance details

Defined in Grisette.Internal.Core.Data.Class.SymOrd

Methods

liftSymCompare :: (a -> b -> Union Ordering) -> Union a -> Union b -> Union Ordering Source #

TryMerge Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

AllSyms1 Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

liftAllSymsS :: (a -> [SomeSym] -> [SomeSym]) -> Union a -> [SomeSym] -> [SomeSym] Source #

ToCon1 Union Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

liftToCon :: (a -> Maybe b) -> Union a -> Maybe (Union b) Source #

ToSym1 Union Union Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

liftToSym :: Mergeable b => (a -> b) -> Union a -> Union b Source #

(GenSym spec a, Mergeable a) => GenSym spec (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Data.Class.GenSym

Methods

fresh :: MonadFresh m => spec -> m (Union (Union a)) Source #

GenSym spec a => GenSymSimple spec (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Data.Class.GenSym

Methods

simpleFresh :: MonadFresh m => spec -> m (Union a) Source #

(Solvable c t, Mergeable t) => Solvable c (Union t) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

(ToSym a b, Mergeable b) => ToSym a (Union b) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

toSym :: a -> Union b Source #

(Mergeable v, UnifiedITEOp 'Sym v) => UnifiedITEOp 'Sym (Union v) Source # 
Instance details

Defined in Grisette.Unified.Internal.Class.UnifiedITEOp

Methods

withBaseITEOp :: (If (IsConMode 'Sym) () (ITEOp (Union v)) => r) -> r Source #

UnifiedSymEq 'Sym v => UnifiedSymEq 'Sym (Union v) Source # 
Instance details

Defined in Grisette.Unified.Internal.Class.UnifiedSymEq

Methods

withBaseSymEq :: (If (IsConMode 'Sym) (Eq (Union v)) (SymEq (Union v)) => r) -> r Source #

UnifiedSymOrd 'Sym v => UnifiedSymOrd 'Sym (Union v) Source # 
Instance details

Defined in Grisette.Unified.Internal.Class.UnifiedSymOrd

Methods

withBaseSymOrd :: (If (IsConMode 'Sym) (Ord (Union v)) (SymOrd (Union v)) => r) -> r Source #

Lift a => Lift (Union a :: Type) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

lift :: Quote m => Union a -> m Exp #

liftTyped :: forall (m :: Type -> Type). Quote m => Union a -> Code m (Union a) #

(IsString a, Mergeable a) => IsString (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

fromString :: String -> Union a #

(Num a, Mergeable a) => Num (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

(+) :: Union a -> Union a -> Union a #

(-) :: Union a -> Union a -> Union a #

(*) :: Union a -> Union a -> Union a #

negate :: Union a -> Union a #

abs :: Union a -> Union a #

signum :: Union a -> Union a #

fromInteger :: Integer -> Union a #

Show a => Show (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

showsPrec :: Int -> Union a -> ShowS #

show :: Union a -> String #

showList :: [Union a] -> ShowS #

NFData a => NFData (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

rnf :: Union a -> () #

Eq a => Eq (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

(==) :: Union a -> Union a -> Bool #

(/=) :: Union a -> Union a -> Bool #

EvalSym a => EvalSym (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

evalSym :: Bool -> Model -> Union a -> Union a Source #

ExtractSym a => ExtractSym (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

(ITEOp a, Mergeable a) => ITEOp (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

symIte :: SymBool -> Union a -> Union a -> Union a Source #

(LogicalOp a, Mergeable a) => LogicalOp (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

true :: Union a Source #

false :: Union a Source #

(.||) :: Union a -> Union a -> Union a Source #

(.&&) :: Union a -> Union a -> Union a Source #

symNot :: Union a -> Union a Source #

symXor :: Union a -> Union a -> Union a Source #

symImplies :: Union a -> Union a -> Union a Source #

Mergeable a => Mergeable (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

PPrint a => PPrint (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

pformat :: Union a -> Doc ann Source #

pformatPrec :: Int -> Union a -> Doc ann Source #

pformatList :: [Union a] -> Doc ann Source #

Mergeable a => SimpleMergeable (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

mrgIte :: SymBool -> Union a -> Union a -> Union a Source #

SubstSym a => SubstSym (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

substSym :: forall cb sb (knd :: SymbolKind). (LinkedRep cb sb, IsSymbolKind knd) => TypedSymbol knd cb -> sb -> Union a -> Union a Source #

SymEq a => SymEq (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

SymOrd a => SymOrd (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Data.Class.SymOrd

AllSyms a => AllSyms (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

allSymsS :: Union a -> [SomeSym] -> [SomeSym] Source #

allSyms :: Union a -> [SomeSym] Source #

Hashable a => Hashable (Union a) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

hashWithSalt :: Int -> Union a -> Int #

hash :: Union a -> Int #

(GenSym a a, Mergeable a) => GenSym (Union a) a Source # 
Instance details

Defined in Grisette.Internal.Core.Data.Class.GenSym

Methods

fresh :: MonadFresh m => Union a -> m (Union a) Source #

(ToCon a b, Mergeable a) => ToCon (Union a) b Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

toCon :: Union a -> Maybe b Source #

ToSym (Union Integer) SymInteger Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

ToSym (Union Bool) SymBool Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

UnionWithExcept (Union (Either e v)) Union e v Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

UnionWithExcept (Union (CBMCEither e v)) Union e v Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.CBMCExcept

(Function f arg ret, Mergeable f, Mergeable ret) => Function (Union f) arg (Union ret) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

(#) :: Union f -> arg -> Union ret Source #

ToCon a b => ToCon (Union a) (Union b) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

toCon :: Union a -> Maybe (Union b) Source #

(KnownNat n, 1 <= n) => ToSym (Union (IntN n)) (SymIntN n) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

toSym :: Union (IntN n) -> SymIntN n Source #

(KnownNat n, 1 <= n) => ToSym (Union (WordN n)) (SymWordN n) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

toSym :: Union (WordN n) -> SymWordN n Source #

ToSym a b => ToSym (Union a) (Union b) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

toSym :: Union a -> Union b Source #

(SupportedPrim (ca --> cb), LinkedRep ca sa, LinkedRep cb sb) => ToSym (Union (ca --> cb)) (sa -~> sb) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

toSym :: Union (ca --> cb) -> sa -~> sb Source #

(SupportedPrim (ca =-> cb), LinkedRep ca sa, LinkedRep cb sb) => ToSym (Union (ca =-> cb)) (sa =~> sb) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

toSym :: Union (ca =-> cb) -> sa =~> sb Source #

(IsConcrete k, Mergeable t) => Mergeable (HashMap k (Union (Maybe t))) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

(IsConcrete k, Mergeable t) => SimpleMergeable (HashMap k (Union (Maybe t))) Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

Methods

mrgIte :: SymBool -> HashMap k (Union (Maybe t)) -> HashMap k (Union (Maybe t)) -> HashMap k (Union (Maybe t)) Source #

unionUnaryOp :: (a -> a) -> Union a -> Union a Source #

Lift a unary operation to Union.

unionBinOp :: (a -> a -> a) -> Union a -> Union a -> Union a Source #

Lift a binary operation to Union.

liftUnion :: forall u a. (Mergeable a, SymBranching u, Applicative u) => Union a -> u a Source #

Lift the Union to any Applicative SymBranching.

liftToMonadUnion :: (Mergeable a, MonadUnion u) => Union a -> u a Source #

Alias for liftUnion, but for monads.

unionBase :: Union a -> UnionBase a Source #

Extract the underlying Union. May be unmerged.

unionMergingStrategy :: Union a -> Maybe (MergingStrategy a) Source #

Get the (possibly empty) cached merging strategy.

isMerged :: Union a -> Bool Source #

Check if a Union is already merged.

unionSize :: Union a -> Int Source #

The size of a union is defined as the number of branches. For example,

>>> unionSize (return True)
1
>>> unionSize (mrgIf "a" (return 1) (return 2) :: Union Integer)
2
>>> unionSize (choose [1..7] "a" :: Union Integer)
7

class (Eq t, Ord t, Hashable t) => IsConcrete t Source #

Tag for concrete types. Useful for specifying the merge strategy for some parametrized types where we should have different merge strategy for symbolic and concrete ones.

Instances

Instances details
IsConcrete Integer Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union

IsConcrete Bool Source # 
Instance details

Defined in Grisette.Internal.Core.Control.Monad.Union