{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

-- |
-- Module      :   Grisette.Internal.Core.Data.Class.GenSym
-- Copyright   :   (c) Sirui Lu 2021-2024
-- License     :   BSD-3-Clause (see the LICENSE file)
--
-- Maintainer  :   siruilu@cs.washington.edu
-- Stability   :   Experimental
-- Portability :   GHC only
module Grisette.Internal.Core.Data.Class.GenSym
  ( -- * Indices and identifiers for fresh symbolic value generation
    FreshIndex (..),

    -- * Monad for fresh symbolic value generation
    MonadFresh (..),
    nextFreshIndex,
    liftFresh,
    FreshT (FreshT, runFreshTFromIndex),
    Fresh,
    runFreshT,
    runFresh,
    mrgRunFreshT,
    freshString,

    -- * Symbolic value generation
    GenSym (..),
    GenSymSimple (..),
    genSym,
    genSymSimple,
    derivedNoSpecFresh,
    derivedNoSpecSimpleFresh,
    derivedSameShapeSimpleFresh,

    -- * Symbolic choices
    chooseFresh,
    chooseSimpleFresh,
    chooseUnionFresh,
    choose,
    chooseSimple,
    chooseUnion,

    -- * Some common GenSym specifications
    ListSpec (..),
    SimpleListSpec (..),
    EnumGenBound (..),
    EnumGenUpperBound (..),
  )
where

import Control.Monad.Except
  ( ExceptT (ExceptT),
    MonadError (catchError, throwError),
  )
import Control.Monad.Identity (Identity (runIdentity))
import Control.Monad.RWS.Class
  ( MonadRWS,
    MonadReader (ask, local),
    MonadState (get, put),
    MonadWriter (listen, pass, writer),
    asks,
    gets,
  )
import qualified Control.Monad.RWS.Lazy as RWSLazy
import qualified Control.Monad.RWS.Strict as RWSStrict
import Control.Monad.Reader (ReaderT (ReaderT))
import Control.Monad.Signatures (Catch)
import qualified Control.Monad.State.Lazy as StateLazy
import qualified Control.Monad.State.Strict as StateStrict
import Control.Monad.Trans.Class
  ( MonadTrans (lift),
  )
import Control.Monad.Trans.Maybe (MaybeT (MaybeT))
import qualified Control.Monad.Writer.Lazy as WriterLazy
import qualified Control.Monad.Writer.Strict as WriterStrict
import Data.Bifunctor (Bifunctor (first))
import qualified Data.ByteString as B
import Data.Int (Int16, Int32, Int64, Int8)
import Data.List (groupBy, sortOn)
import Data.Ratio (Ratio)
import Data.String (IsString (fromString))
import qualified Data.Text as T
import Data.Typeable (Typeable)
import Data.Word (Word16, Word32, Word64, Word8)
import GHC.TypeNats (KnownNat, type (<=))
import Generics.Deriving
  ( Generic (Rep, from, to),
    K1 (K1),
    M1 (M1),
    U1 (U1),
    type (:*:) ((:*:)),
    type (:+:) (L1, R1),
  )
import Grisette.Internal.Core.Control.Monad.Union
  ( Union,
    isMerged,
    unionBase,
  )
import Grisette.Internal.Core.Data.Class.Mergeable
  ( Mergeable (rootStrategy, sortIndices),
    Mergeable1 (liftRootStrategy),
    Mergeable2 (liftRootStrategy2),
    MergingStrategy (SimpleStrategy),
    rootStrategy1,
    wrapStrategy,
  )
import Grisette.Internal.Core.Data.Class.SimpleMergeable
  ( SimpleMergeable (mrgIte),
    SimpleMergeable1 (liftMrgIte),
    SymBranching (mrgIfPropagatedStrategy, mrgIfWithStrategy),
    mrgIf,
  )
import Grisette.Internal.Core.Data.Class.Solvable (Solvable (isym))
import Grisette.Internal.Core.Data.Class.TryMerge
  ( TryMerge (tryMergeWithStrategy),
    mrgSingle,
    tryMerge,
  )
import Grisette.Internal.Core.Data.Symbol (Identifier)
import Grisette.Internal.Internal.Decl.Core.Data.UnionBase
  ( UnionBase (UnionIf, UnionSingle),
  )
import Grisette.Internal.SymPrim.BV (IntN, WordN)
import Grisette.Internal.SymPrim.FP (FP, FPRoundingMode, ValidFP)
import Grisette.Internal.SymPrim.GeneralFun (type (-->))
import Grisette.Internal.SymPrim.Prim.Term
  ( LinkedRep,
    SupportedNonFuncPrim,
    SupportedPrim,
  )
import Grisette.Internal.SymPrim.SymAlgReal (SymAlgReal)
import Grisette.Internal.SymPrim.SymBV
  ( SymIntN,
    SymWordN,
  )
import Grisette.Internal.SymPrim.SymBool (SymBool)
import Grisette.Internal.SymPrim.SymFP (SymFP, SymFPRoundingMode)
import Grisette.Internal.SymPrim.SymGeneralFun (type (-~>) (SymGeneralFun))
import Grisette.Internal.SymPrim.SymInteger (SymInteger)
import Grisette.Internal.SymPrim.SymTabularFun (type (=~>) (SymTabularFun))
import Grisette.Internal.SymPrim.TabularFun (type (=->))

-- $setup
-- >>> import Grisette.Core
-- >>> import Grisette.SymPrim

-- | Index type used for 'GenSym'.
--
-- To generate fresh variables, a monadic stateful context will be maintained.
-- The index should be increased every time a new symbolic constant is
-- generated.
newtype FreshIndex = FreshIndex Int
  deriving (Int -> FreshIndex -> ShowS
[FreshIndex] -> ShowS
FreshIndex -> String
(Int -> FreshIndex -> ShowS)
-> (FreshIndex -> String)
-> ([FreshIndex] -> ShowS)
-> Show FreshIndex
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FreshIndex -> ShowS
showsPrec :: Int -> FreshIndex -> ShowS
$cshow :: FreshIndex -> String
show :: FreshIndex -> String
$cshowList :: [FreshIndex] -> ShowS
showList :: [FreshIndex] -> ShowS
Show)
  deriving (FreshIndex -> FreshIndex -> Bool
(FreshIndex -> FreshIndex -> Bool)
-> (FreshIndex -> FreshIndex -> Bool) -> Eq FreshIndex
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FreshIndex -> FreshIndex -> Bool
== :: FreshIndex -> FreshIndex -> Bool
$c/= :: FreshIndex -> FreshIndex -> Bool
/= :: FreshIndex -> FreshIndex -> Bool
Eq, Eq FreshIndex
Eq FreshIndex =>
(FreshIndex -> FreshIndex -> Ordering)
-> (FreshIndex -> FreshIndex -> Bool)
-> (FreshIndex -> FreshIndex -> Bool)
-> (FreshIndex -> FreshIndex -> Bool)
-> (FreshIndex -> FreshIndex -> Bool)
-> (FreshIndex -> FreshIndex -> FreshIndex)
-> (FreshIndex -> FreshIndex -> FreshIndex)
-> Ord FreshIndex
FreshIndex -> FreshIndex -> Bool
FreshIndex -> FreshIndex -> Ordering
FreshIndex -> FreshIndex -> FreshIndex
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: FreshIndex -> FreshIndex -> Ordering
compare :: FreshIndex -> FreshIndex -> Ordering
$c< :: FreshIndex -> FreshIndex -> Bool
< :: FreshIndex -> FreshIndex -> Bool
$c<= :: FreshIndex -> FreshIndex -> Bool
<= :: FreshIndex -> FreshIndex -> Bool
$c> :: FreshIndex -> FreshIndex -> Bool
> :: FreshIndex -> FreshIndex -> Bool
$c>= :: FreshIndex -> FreshIndex -> Bool
>= :: FreshIndex -> FreshIndex -> Bool
$cmax :: FreshIndex -> FreshIndex -> FreshIndex
max :: FreshIndex -> FreshIndex -> FreshIndex
$cmin :: FreshIndex -> FreshIndex -> FreshIndex
min :: FreshIndex -> FreshIndex -> FreshIndex
Ord, Integer -> FreshIndex
FreshIndex -> FreshIndex
FreshIndex -> FreshIndex -> FreshIndex
(FreshIndex -> FreshIndex -> FreshIndex)
-> (FreshIndex -> FreshIndex -> FreshIndex)
-> (FreshIndex -> FreshIndex -> FreshIndex)
-> (FreshIndex -> FreshIndex)
-> (FreshIndex -> FreshIndex)
-> (FreshIndex -> FreshIndex)
-> (Integer -> FreshIndex)
-> Num FreshIndex
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
$c+ :: FreshIndex -> FreshIndex -> FreshIndex
+ :: FreshIndex -> FreshIndex -> FreshIndex
$c- :: FreshIndex -> FreshIndex -> FreshIndex
- :: FreshIndex -> FreshIndex -> FreshIndex
$c* :: FreshIndex -> FreshIndex -> FreshIndex
* :: FreshIndex -> FreshIndex -> FreshIndex
$cnegate :: FreshIndex -> FreshIndex
negate :: FreshIndex -> FreshIndex
$cabs :: FreshIndex -> FreshIndex
abs :: FreshIndex -> FreshIndex
$csignum :: FreshIndex -> FreshIndex
signum :: FreshIndex -> FreshIndex
$cfromInteger :: Integer -> FreshIndex
fromInteger :: Integer -> FreshIndex
Num) via Int

instance Mergeable FreshIndex where
  rootStrategy :: MergingStrategy FreshIndex
rootStrategy = (SymBool -> FreshIndex -> FreshIndex -> FreshIndex)
-> MergingStrategy FreshIndex
forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy ((SymBool -> FreshIndex -> FreshIndex -> FreshIndex)
 -> MergingStrategy FreshIndex)
-> (SymBool -> FreshIndex -> FreshIndex -> FreshIndex)
-> MergingStrategy FreshIndex
forall a b. (a -> b) -> a -> b
$ \SymBool
_ FreshIndex
t FreshIndex
f -> FreshIndex -> FreshIndex -> FreshIndex
forall a. Ord a => a -> a -> a
max FreshIndex
t FreshIndex
f

instance SimpleMergeable FreshIndex where
  mrgIte :: SymBool -> FreshIndex -> FreshIndex -> FreshIndex
mrgIte SymBool
_ = FreshIndex -> FreshIndex -> FreshIndex
forall a. Ord a => a -> a -> a
max

-- | Monad class for fresh symbolic value generation.
--
-- The monad should be a reader monad for the 'Identifier' and a state monad for
-- the t'FreshIndex'.
class (Monad m) => MonadFresh m where
  -- | Get the current index for fresh variable generation.
  getFreshIndex :: m FreshIndex

  -- | Set the current index for fresh variable generation.
  setFreshIndex :: FreshIndex -> m ()

  -- | Get the identifier.
  getIdentifier :: m Identifier

  -- | Change the identifier locally and use a new index from 0 locally.
  localIdentifier :: (Identifier -> Identifier) -> m a -> m a

-- | Get the next fresh index and increase the current index.
nextFreshIndex :: (MonadFresh m) => m FreshIndex
nextFreshIndex :: forall (m :: * -> *). MonadFresh m => m FreshIndex
nextFreshIndex = do
  curr <- m FreshIndex
forall (m :: * -> *). MonadFresh m => m FreshIndex
getFreshIndex
  let new = FreshIndex
curr FreshIndex -> FreshIndex -> FreshIndex
forall a. Num a => a -> a -> a
+ FreshIndex
1
  setFreshIndex new
  return curr

-- | Lifts an @`Fresh` a@ into any `MonadFresh`.
liftFresh :: (MonadFresh m) => Fresh a -> m a
liftFresh :: forall (m :: * -> *) a. MonadFresh m => Fresh a -> m a
liftFresh (FreshT Identifier -> FreshIndex -> Identity (a, FreshIndex)
f) = do
  index <- m FreshIndex
forall (m :: * -> *). MonadFresh m => m FreshIndex
nextFreshIndex
  ident <- getIdentifier
  let (a, newIdx) = runIdentity $ f ident index
  setFreshIndex newIdx
  return a

-- | Generate a fresh string with the given postfix.
--
-- >>> runFresh (freshString "b") "a" :: String
-- "a@0[b]"
freshString :: (MonadFresh m, IsString s) => String -> m s
freshString :: forall (m :: * -> *) s. (MonadFresh m, IsString s) => String -> m s
freshString String
postfix = do
  ident <- m Identifier
forall (m :: * -> *). MonadFresh m => m Identifier
getIdentifier
  FreshIndex index <- nextFreshIndex
  return $
    fromString $
      show ident <> "@" <> show index <> "[" <> postfix <> "]"

-- | A symbolic generation monad transformer.
--
-- It is a reader monad transformer for an identifier and a state monad
-- transformer for indices.
--
-- Each time a fresh symbolic variable is generated, the index should be
-- increased.
newtype FreshT m a = FreshT
  { forall (m :: * -> *) a.
FreshT m a -> Identifier -> FreshIndex -> m (a, FreshIndex)
runFreshTFromIndex :: Identifier -> FreshIndex -> m (a, FreshIndex)
  }

instance
  (Mergeable a, Mergeable1 m) =>
  Mergeable (FreshT m a)
  where
  rootStrategy :: MergingStrategy (FreshT m a)
rootStrategy =
    MergingStrategy (Identifier -> FreshIndex -> m (a, FreshIndex))
-> ((Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (FreshT m a -> Identifier -> FreshIndex -> m (a, FreshIndex))
-> MergingStrategy (FreshT m a)
forall a b.
MergingStrategy a -> (a -> b) -> (b -> a) -> MergingStrategy b
wrapStrategy
      (MergingStrategy (FreshIndex -> m (a, FreshIndex))
-> MergingStrategy (Identifier -> FreshIndex -> m (a, FreshIndex))
forall a. MergingStrategy a -> MergingStrategy (Identifier -> a)
forall (u :: * -> *) a.
Mergeable1 u =>
MergingStrategy a -> MergingStrategy (u a)
liftRootStrategy (MergingStrategy (m (a, FreshIndex))
-> MergingStrategy (FreshIndex -> m (a, FreshIndex))
forall a. MergingStrategy a -> MergingStrategy (FreshIndex -> a)
forall (u :: * -> *) a.
Mergeable1 u =>
MergingStrategy a -> MergingStrategy (u a)
liftRootStrategy MergingStrategy (m (a, FreshIndex))
forall a (u :: * -> *).
(Mergeable a, Mergeable1 u) =>
MergingStrategy (u a)
rootStrategy1))
      (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT
      FreshT m a -> Identifier -> FreshIndex -> m (a, FreshIndex)
forall (m :: * -> *) a.
FreshT m a -> Identifier -> FreshIndex -> m (a, FreshIndex)
runFreshTFromIndex

instance (Mergeable1 m) => Mergeable1 (FreshT m) where
  liftRootStrategy :: forall a. MergingStrategy a -> MergingStrategy (FreshT m a)
liftRootStrategy MergingStrategy a
m =
    MergingStrategy (Identifier -> FreshIndex -> m (a, FreshIndex))
-> ((Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (FreshT m a -> Identifier -> FreshIndex -> m (a, FreshIndex))
-> MergingStrategy (FreshT m a)
forall a b.
MergingStrategy a -> (a -> b) -> (b -> a) -> MergingStrategy b
wrapStrategy
      ( MergingStrategy (FreshIndex -> m (a, FreshIndex))
-> MergingStrategy (Identifier -> FreshIndex -> m (a, FreshIndex))
forall a. MergingStrategy a -> MergingStrategy (Identifier -> a)
forall (u :: * -> *) a.
Mergeable1 u =>
MergingStrategy a -> MergingStrategy (u a)
liftRootStrategy (MergingStrategy (FreshIndex -> m (a, FreshIndex))
 -> MergingStrategy (Identifier -> FreshIndex -> m (a, FreshIndex)))
-> (MergingStrategy (a, FreshIndex)
    -> MergingStrategy (FreshIndex -> m (a, FreshIndex)))
-> MergingStrategy (a, FreshIndex)
-> MergingStrategy (Identifier -> FreshIndex -> m (a, FreshIndex))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MergingStrategy (m (a, FreshIndex))
-> MergingStrategy (FreshIndex -> m (a, FreshIndex))
forall a. MergingStrategy a -> MergingStrategy (FreshIndex -> a)
forall (u :: * -> *) a.
Mergeable1 u =>
MergingStrategy a -> MergingStrategy (u a)
liftRootStrategy (MergingStrategy (m (a, FreshIndex))
 -> MergingStrategy (FreshIndex -> m (a, FreshIndex)))
-> (MergingStrategy (a, FreshIndex)
    -> MergingStrategy (m (a, FreshIndex)))
-> MergingStrategy (a, FreshIndex)
-> MergingStrategy (FreshIndex -> m (a, FreshIndex))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MergingStrategy (a, FreshIndex)
-> MergingStrategy (m (a, FreshIndex))
forall a. MergingStrategy a -> MergingStrategy (m a)
forall (u :: * -> *) a.
Mergeable1 u =>
MergingStrategy a -> MergingStrategy (u a)
liftRootStrategy (MergingStrategy (a, FreshIndex)
 -> MergingStrategy (Identifier -> FreshIndex -> m (a, FreshIndex)))
-> MergingStrategy (a, FreshIndex)
-> MergingStrategy (Identifier -> FreshIndex -> m (a, FreshIndex))
forall a b. (a -> b) -> a -> b
$
          MergingStrategy a
-> MergingStrategy FreshIndex -> MergingStrategy (a, FreshIndex)
forall a b.
MergingStrategy a -> MergingStrategy b -> MergingStrategy (a, b)
forall (u :: * -> * -> *) a b.
Mergeable2 u =>
MergingStrategy a -> MergingStrategy b -> MergingStrategy (u a b)
liftRootStrategy2 MergingStrategy a
m MergingStrategy FreshIndex
forall a. Mergeable a => MergingStrategy a
rootStrategy
      )
      (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT
      FreshT m a -> Identifier -> FreshIndex -> m (a, FreshIndex)
forall (m :: * -> *) a.
FreshT m a -> Identifier -> FreshIndex -> m (a, FreshIndex)
runFreshTFromIndex

instance
  (SymBranching m, Mergeable a) =>
  SimpleMergeable (FreshT m a)
  where
  mrgIte :: SymBool -> FreshT m a -> FreshT m a -> FreshT m a
mrgIte = SymBool -> FreshT m a -> FreshT m a -> FreshT m a
forall (u :: * -> *) a.
(SymBranching u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf

instance
  (SymBranching m) =>
  SimpleMergeable1 (FreshT m)
  where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a)
-> SymBool -> FreshT m a -> FreshT m a -> FreshT m a
liftMrgIte SymBool -> a -> a -> a
m = MergingStrategy a
-> SymBool -> FreshT m a -> FreshT m a -> FreshT m a
forall a.
MergingStrategy a
-> SymBool -> FreshT m a -> FreshT m a -> FreshT m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy ((SymBool -> a -> a -> a) -> MergingStrategy a
forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)

instance (TryMerge m) => TryMerge (FreshT m) where
  tryMergeWithStrategy :: forall a. MergingStrategy a -> FreshT m a -> FreshT m a
tryMergeWithStrategy MergingStrategy a
s (FreshT Identifier -> FreshIndex -> m (a, FreshIndex)
f) =
    (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall a b. (a -> b) -> a -> b
$ \Identifier
ident FreshIndex
index ->
      MergingStrategy (a, FreshIndex)
-> m (a, FreshIndex) -> m (a, FreshIndex)
forall a. MergingStrategy a -> m a -> m a
forall (m :: * -> *) a.
TryMerge m =>
MergingStrategy a -> m a -> m a
tryMergeWithStrategy (MergingStrategy a
-> MergingStrategy FreshIndex -> MergingStrategy (a, FreshIndex)
forall a b.
MergingStrategy a -> MergingStrategy b -> MergingStrategy (a, b)
forall (u :: * -> * -> *) a b.
Mergeable2 u =>
MergingStrategy a -> MergingStrategy b -> MergingStrategy (u a b)
liftRootStrategy2 MergingStrategy a
s MergingStrategy FreshIndex
forall a. Mergeable a => MergingStrategy a
rootStrategy) (m (a, FreshIndex) -> m (a, FreshIndex))
-> m (a, FreshIndex) -> m (a, FreshIndex)
forall a b. (a -> b) -> a -> b
$ Identifier -> FreshIndex -> m (a, FreshIndex)
f Identifier
ident FreshIndex
index

instance
  (SymBranching m) =>
  SymBranching (FreshT m)
  where
  mrgIfWithStrategy :: forall a.
MergingStrategy a
-> SymBool -> FreshT m a -> FreshT m a -> FreshT m a
mrgIfWithStrategy MergingStrategy a
s SymBool
cond (FreshT Identifier -> FreshIndex -> m (a, FreshIndex)
t) (FreshT Identifier -> FreshIndex -> m (a, FreshIndex)
f) =
    (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall a b. (a -> b) -> a -> b
$ \Identifier
ident FreshIndex
index ->
      MergingStrategy (a, FreshIndex)
-> SymBool
-> m (a, FreshIndex)
-> m (a, FreshIndex)
-> m (a, FreshIndex)
forall a. MergingStrategy a -> SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy
        (MergingStrategy a
-> MergingStrategy FreshIndex -> MergingStrategy (a, FreshIndex)
forall a b.
MergingStrategy a -> MergingStrategy b -> MergingStrategy (a, b)
forall (u :: * -> * -> *) a b.
Mergeable2 u =>
MergingStrategy a -> MergingStrategy b -> MergingStrategy (u a b)
liftRootStrategy2 MergingStrategy a
s MergingStrategy FreshIndex
forall a. Mergeable a => MergingStrategy a
rootStrategy)
        SymBool
cond
        (Identifier -> FreshIndex -> m (a, FreshIndex)
t Identifier
ident FreshIndex
index)
        (Identifier -> FreshIndex -> m (a, FreshIndex)
f Identifier
ident FreshIndex
index)
  mrgIfPropagatedStrategy :: forall a. SymBool -> FreshT m a -> FreshT m a -> FreshT m a
mrgIfPropagatedStrategy SymBool
cond (FreshT Identifier -> FreshIndex -> m (a, FreshIndex)
t) (FreshT Identifier -> FreshIndex -> m (a, FreshIndex)
f) =
    (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall a b. (a -> b) -> a -> b
$ \Identifier
ident FreshIndex
index ->
      SymBool
-> m (a, FreshIndex) -> m (a, FreshIndex) -> m (a, FreshIndex)
forall a. SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
SymBool -> u a -> u a -> u a
mrgIfPropagatedStrategy SymBool
cond (Identifier -> FreshIndex -> m (a, FreshIndex)
t Identifier
ident FreshIndex
index) (Identifier -> FreshIndex -> m (a, FreshIndex)
f Identifier
ident FreshIndex
index)

-- | Run the symbolic generation with the given identifier and 0 as the initial
-- index.
runFreshT :: (Monad m) => FreshT m a -> Identifier -> m a
runFreshT :: forall (m :: * -> *) a. Monad m => FreshT m a -> Identifier -> m a
runFreshT FreshT m a
m Identifier
ident = (a, FreshIndex) -> a
forall a b. (a, b) -> a
fst ((a, FreshIndex) -> a) -> m (a, FreshIndex) -> m a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FreshT m a -> Identifier -> FreshIndex -> m (a, FreshIndex)
forall (m :: * -> *) a.
FreshT m a -> Identifier -> FreshIndex -> m (a, FreshIndex)
runFreshTFromIndex FreshT m a
m Identifier
ident (Int -> FreshIndex
FreshIndex Int
0)

-- | Run the symbolic generation with the given identifier and 0 as the initial
-- index, and try to merge the result.
mrgRunFreshT ::
  (Monad m, TryMerge m, Mergeable a) =>
  FreshT m a ->
  Identifier ->
  m a
mrgRunFreshT :: forall (m :: * -> *) a.
(Monad m, TryMerge m, Mergeable a) =>
FreshT m a -> Identifier -> m a
mrgRunFreshT FreshT m a
m Identifier
ident = m a -> m a
forall (m :: * -> *) a. (TryMerge m, Mergeable a) => m a -> m a
tryMerge (m a -> m a) -> m a -> m a
forall a b. (a -> b) -> a -> b
$ FreshT m a -> Identifier -> m a
forall (m :: * -> *) a. Monad m => FreshT m a -> Identifier -> m a
runFreshT FreshT m a
m Identifier
ident

instance (Functor f) => Functor (FreshT f) where
  fmap :: forall a b. (a -> b) -> FreshT f a -> FreshT f b
fmap a -> b
f (FreshT Identifier -> FreshIndex -> f (a, FreshIndex)
s) = (Identifier -> FreshIndex -> f (b, FreshIndex)) -> FreshT f b
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> f (b, FreshIndex)) -> FreshT f b)
-> (Identifier -> FreshIndex -> f (b, FreshIndex)) -> FreshT f b
forall a b. (a -> b) -> a -> b
$ \Identifier
ident FreshIndex
idx -> (a -> b) -> (a, FreshIndex) -> (b, FreshIndex)
forall a b c. (a -> b) -> (a, c) -> (b, c)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first a -> b
f ((a, FreshIndex) -> (b, FreshIndex))
-> f (a, FreshIndex) -> f (b, FreshIndex)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Identifier -> FreshIndex -> f (a, FreshIndex)
s Identifier
ident FreshIndex
idx

instance (Applicative m, Monad m) => Applicative (FreshT m) where
  pure :: forall a. a -> FreshT m a
pure a
a = (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall a b. (a -> b) -> a -> b
$ \Identifier
_ FreshIndex
idx -> (a, FreshIndex) -> m (a, FreshIndex)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
a, FreshIndex
idx)
  FreshT Identifier -> FreshIndex -> m (a -> b, FreshIndex)
fs <*> :: forall a b. FreshT m (a -> b) -> FreshT m a -> FreshT m b
<*> FreshT Identifier -> FreshIndex -> m (a, FreshIndex)
as = (Identifier -> FreshIndex -> m (b, FreshIndex)) -> FreshT m b
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m (b, FreshIndex)) -> FreshT m b)
-> (Identifier -> FreshIndex -> m (b, FreshIndex)) -> FreshT m b
forall a b. (a -> b) -> a -> b
$ \Identifier
ident FreshIndex
idx -> do
    (f, idx') <- Identifier -> FreshIndex -> m (a -> b, FreshIndex)
fs Identifier
ident FreshIndex
idx
    (a, idx'') <- as ident idx'
    return (f a, idx'')

instance (Monad m) => Monad (FreshT m) where
  (FreshT Identifier -> FreshIndex -> m (a, FreshIndex)
s) >>= :: forall a b. FreshT m a -> (a -> FreshT m b) -> FreshT m b
>>= a -> FreshT m b
f = (Identifier -> FreshIndex -> m (b, FreshIndex)) -> FreshT m b
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m (b, FreshIndex)) -> FreshT m b)
-> (Identifier -> FreshIndex -> m (b, FreshIndex)) -> FreshT m b
forall a b. (a -> b) -> a -> b
$ \Identifier
ident FreshIndex
idx -> do
    (a, idx') <- Identifier -> FreshIndex -> m (a, FreshIndex)
s Identifier
ident FreshIndex
idx
    runFreshTFromIndex (f a) ident idx'

instance MonadTrans FreshT where
  lift :: forall (m :: * -> *) a. Monad m => m a -> FreshT m a
lift m a
x = (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall a b. (a -> b) -> a -> b
$ \Identifier
_ FreshIndex
index -> (,FreshIndex
index) (a -> (a, FreshIndex)) -> m a -> m (a, FreshIndex)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m a
x

liftFreshTCache :: (Functor m) => Catch e m (a, FreshIndex) -> Catch e (FreshT m) a
liftFreshTCache :: forall (m :: * -> *) e a.
Functor m =>
Catch e m (a, FreshIndex) -> Catch e (FreshT m) a
liftFreshTCache Catch e m (a, FreshIndex)
catchE (FreshT Identifier -> FreshIndex -> m (a, FreshIndex)
m) e -> FreshT m a
h =
  (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall a b. (a -> b) -> a -> b
$ \Identifier
ident FreshIndex
index -> Identifier -> FreshIndex -> m (a, FreshIndex)
m Identifier
ident FreshIndex
index Catch e m (a, FreshIndex)
`catchE` \e
e -> FreshT m a -> Identifier -> FreshIndex -> m (a, FreshIndex)
forall (m :: * -> *) a.
FreshT m a -> Identifier -> FreshIndex -> m (a, FreshIndex)
runFreshTFromIndex (e -> FreshT m a
h e
e) Identifier
ident FreshIndex
index

instance (MonadError e m) => MonadError e (FreshT m) where
  throwError :: forall a. e -> FreshT m a
throwError = m a -> FreshT m a
forall (m :: * -> *) a. Monad m => m a -> FreshT m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m a -> FreshT m a) -> (e -> m a) -> e -> FreshT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. e -> m a
forall a. e -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError
  catchError :: forall a. FreshT m a -> (e -> FreshT m a) -> FreshT m a
catchError = Catch e m (a, FreshIndex) -> Catch e (FreshT m) a
forall (m :: * -> *) e a.
Functor m =>
Catch e m (a, FreshIndex) -> Catch e (FreshT m) a
liftFreshTCache Catch e m (a, FreshIndex)
forall a. m a -> (e -> m a) -> m a
forall e (m :: * -> *) a.
MonadError e m =>
m a -> (e -> m a) -> m a
catchError

instance (MonadWriter w m) => MonadWriter w (FreshT m) where
  writer :: forall a. (a, w) -> FreshT m a
writer (a, w)
p = (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall a b. (a -> b) -> a -> b
$ \Identifier
_ FreshIndex
index -> (,FreshIndex
index) (a -> (a, FreshIndex)) -> m a -> m (a, FreshIndex)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (a, w) -> m a
forall a. (a, w) -> m a
forall w (m :: * -> *) a. MonadWriter w m => (a, w) -> m a
writer (a, w)
p
  listen :: forall a. FreshT m a -> FreshT m (a, w)
listen (FreshT Identifier -> FreshIndex -> m (a, FreshIndex)
r) = (Identifier -> FreshIndex -> m ((a, w), FreshIndex))
-> FreshT m (a, w)
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m ((a, w), FreshIndex))
 -> FreshT m (a, w))
-> (Identifier -> FreshIndex -> m ((a, w), FreshIndex))
-> FreshT m (a, w)
forall a b. (a -> b) -> a -> b
$ \Identifier
ident FreshIndex
index -> (\((a
a, FreshIndex
b), w
c) -> ((a
a, w
c), FreshIndex
b)) (((a, FreshIndex), w) -> ((a, w), FreshIndex))
-> m ((a, FreshIndex), w) -> m ((a, w), FreshIndex)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (a, FreshIndex) -> m ((a, FreshIndex), w)
forall a. m a -> m (a, w)
forall w (m :: * -> *) a. MonadWriter w m => m a -> m (a, w)
listen (Identifier -> FreshIndex -> m (a, FreshIndex)
r Identifier
ident FreshIndex
index)
  pass :: forall a. FreshT m (a, w -> w) -> FreshT m a
pass (FreshT Identifier -> FreshIndex -> m ((a, w -> w), FreshIndex)
r) = (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall a b. (a -> b) -> a -> b
$ \Identifier
ident FreshIndex
index -> m ((a, FreshIndex), w -> w) -> m (a, FreshIndex)
forall a. m (a, w -> w) -> m a
forall w (m :: * -> *) a. MonadWriter w m => m (a, w -> w) -> m a
pass (m ((a, FreshIndex), w -> w) -> m (a, FreshIndex))
-> m ((a, FreshIndex), w -> w) -> m (a, FreshIndex)
forall a b. (a -> b) -> a -> b
$ (\((a
a, w -> w
b), FreshIndex
c) -> ((a
a, FreshIndex
c), w -> w
b)) (((a, w -> w), FreshIndex) -> ((a, FreshIndex), w -> w))
-> m ((a, w -> w), FreshIndex) -> m ((a, FreshIndex), w -> w)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Identifier -> FreshIndex -> m ((a, w -> w), FreshIndex)
r Identifier
ident FreshIndex
index

instance (MonadState s m) => MonadState s (FreshT m) where
  get :: FreshT m s
get = (Identifier -> FreshIndex -> m (s, FreshIndex)) -> FreshT m s
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m (s, FreshIndex)) -> FreshT m s)
-> (Identifier -> FreshIndex -> m (s, FreshIndex)) -> FreshT m s
forall a b. (a -> b) -> a -> b
$ \Identifier
_ FreshIndex
index -> (s -> (s, FreshIndex)) -> m (s, FreshIndex)
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets (,FreshIndex
index)
  put :: s -> FreshT m ()
put s
s = (Identifier -> FreshIndex -> m ((), FreshIndex)) -> FreshT m ()
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m ((), FreshIndex)) -> FreshT m ())
-> (Identifier -> FreshIndex -> m ((), FreshIndex)) -> FreshT m ()
forall a b. (a -> b) -> a -> b
$ \Identifier
_ FreshIndex
index -> (,FreshIndex
index) (() -> ((), FreshIndex)) -> m () -> m ((), FreshIndex)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> s -> m ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put s
s

instance (MonadReader r m) => MonadReader r (FreshT m) where
  local :: forall a. (r -> r) -> FreshT m a -> FreshT m a
local r -> r
t (FreshT Identifier -> FreshIndex -> m (a, FreshIndex)
r) = (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall a b. (a -> b) -> a -> b
$ \Identifier
ident FreshIndex
index -> (r -> r) -> m (a, FreshIndex) -> m (a, FreshIndex)
forall a. (r -> r) -> m a -> m a
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local r -> r
t (Identifier -> FreshIndex -> m (a, FreshIndex)
r Identifier
ident FreshIndex
index)
  ask :: FreshT m r
ask = (Identifier -> FreshIndex -> m (r, FreshIndex)) -> FreshT m r
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m (r, FreshIndex)) -> FreshT m r)
-> (Identifier -> FreshIndex -> m (r, FreshIndex)) -> FreshT m r
forall a b. (a -> b) -> a -> b
$ \Identifier
_ FreshIndex
index -> (r -> (r, FreshIndex)) -> m (r, FreshIndex)
forall r (m :: * -> *) a. MonadReader r m => (r -> a) -> m a
asks (,FreshIndex
index)

instance (MonadRWS r w s m) => MonadRWS r w s (FreshT m)

instance (MonadFresh m) => MonadFresh (ExceptT e m) where
  getFreshIndex :: ExceptT e m FreshIndex
getFreshIndex = m FreshIndex -> ExceptT e m FreshIndex
forall (m :: * -> *) a. Monad m => m a -> ExceptT e m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m FreshIndex
forall (m :: * -> *). MonadFresh m => m FreshIndex
getFreshIndex
  setFreshIndex :: FreshIndex -> ExceptT e m ()
setFreshIndex FreshIndex
newIdx = m () -> ExceptT e m ()
forall (m :: * -> *) a. Monad m => m a -> ExceptT e m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> ExceptT e m ()) -> m () -> ExceptT e m ()
forall a b. (a -> b) -> a -> b
$ FreshIndex -> m ()
forall (m :: * -> *). MonadFresh m => FreshIndex -> m ()
setFreshIndex FreshIndex
newIdx
  getIdentifier :: ExceptT e m Identifier
getIdentifier = m Identifier -> ExceptT e m Identifier
forall (m :: * -> *) a. Monad m => m a -> ExceptT e m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m Identifier
forall (m :: * -> *). MonadFresh m => m Identifier
getIdentifier
  localIdentifier :: forall a.
(Identifier -> Identifier) -> ExceptT e m a -> ExceptT e m a
localIdentifier Identifier -> Identifier
f (ExceptT m (Either e a)
m) = m (Either e a) -> ExceptT e m a
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT (m (Either e a) -> ExceptT e m a)
-> m (Either e a) -> ExceptT e m a
forall a b. (a -> b) -> a -> b
$ (Identifier -> Identifier) -> m (Either e a) -> m (Either e a)
forall a. (Identifier -> Identifier) -> m a -> m a
forall (m :: * -> *) a.
MonadFresh m =>
(Identifier -> Identifier) -> m a -> m a
localIdentifier Identifier -> Identifier
f m (Either e a)
m

instance (MonadFresh m, Monoid w) => MonadFresh (WriterLazy.WriterT w m) where
  getFreshIndex :: WriterT w m FreshIndex
getFreshIndex = m FreshIndex -> WriterT w m FreshIndex
forall (m :: * -> *) a. Monad m => m a -> WriterT w m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m FreshIndex
forall (m :: * -> *). MonadFresh m => m FreshIndex
getFreshIndex
  setFreshIndex :: FreshIndex -> WriterT w m ()
setFreshIndex FreshIndex
newIdx = m () -> WriterT w m ()
forall (m :: * -> *) a. Monad m => m a -> WriterT w m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> WriterT w m ()) -> m () -> WriterT w m ()
forall a b. (a -> b) -> a -> b
$ FreshIndex -> m ()
forall (m :: * -> *). MonadFresh m => FreshIndex -> m ()
setFreshIndex FreshIndex
newIdx
  getIdentifier :: WriterT w m Identifier
getIdentifier = m Identifier -> WriterT w m Identifier
forall (m :: * -> *) a. Monad m => m a -> WriterT w m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m Identifier
forall (m :: * -> *). MonadFresh m => m Identifier
getIdentifier
  localIdentifier :: forall a.
(Identifier -> Identifier) -> WriterT w m a -> WriterT w m a
localIdentifier Identifier -> Identifier
f (WriterLazy.WriterT m (a, w)
m) =
    m (a, w) -> WriterT w m a
forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
WriterLazy.WriterT (m (a, w) -> WriterT w m a) -> m (a, w) -> WriterT w m a
forall a b. (a -> b) -> a -> b
$ (Identifier -> Identifier) -> m (a, w) -> m (a, w)
forall a. (Identifier -> Identifier) -> m a -> m a
forall (m :: * -> *) a.
MonadFresh m =>
(Identifier -> Identifier) -> m a -> m a
localIdentifier Identifier -> Identifier
f m (a, w)
m

instance (MonadFresh m, Monoid w) => MonadFresh (WriterStrict.WriterT w m) where
  getFreshIndex :: WriterT w m FreshIndex
getFreshIndex = m FreshIndex -> WriterT w m FreshIndex
forall (m :: * -> *) a. Monad m => m a -> WriterT w m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m FreshIndex
forall (m :: * -> *). MonadFresh m => m FreshIndex
getFreshIndex
  setFreshIndex :: FreshIndex -> WriterT w m ()
setFreshIndex FreshIndex
newIdx = m () -> WriterT w m ()
forall (m :: * -> *) a. Monad m => m a -> WriterT w m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> WriterT w m ()) -> m () -> WriterT w m ()
forall a b. (a -> b) -> a -> b
$ FreshIndex -> m ()
forall (m :: * -> *). MonadFresh m => FreshIndex -> m ()
setFreshIndex FreshIndex
newIdx
  getIdentifier :: WriterT w m Identifier
getIdentifier = m Identifier -> WriterT w m Identifier
forall (m :: * -> *) a. Monad m => m a -> WriterT w m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m Identifier
forall (m :: * -> *). MonadFresh m => m Identifier
getIdentifier
  localIdentifier :: forall a.
(Identifier -> Identifier) -> WriterT w m a -> WriterT w m a
localIdentifier Identifier -> Identifier
f (WriterStrict.WriterT m (a, w)
m) =
    m (a, w) -> WriterT w m a
forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
WriterStrict.WriterT (m (a, w) -> WriterT w m a) -> m (a, w) -> WriterT w m a
forall a b. (a -> b) -> a -> b
$ (Identifier -> Identifier) -> m (a, w) -> m (a, w)
forall a. (Identifier -> Identifier) -> m a -> m a
forall (m :: * -> *) a.
MonadFresh m =>
(Identifier -> Identifier) -> m a -> m a
localIdentifier Identifier -> Identifier
f m (a, w)
m

instance (MonadFresh m) => MonadFresh (StateLazy.StateT s m) where
  getFreshIndex :: StateT s m FreshIndex
getFreshIndex = m FreshIndex -> StateT s m FreshIndex
forall (m :: * -> *) a. Monad m => m a -> StateT s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m FreshIndex
forall (m :: * -> *). MonadFresh m => m FreshIndex
getFreshIndex
  setFreshIndex :: FreshIndex -> StateT s m ()
setFreshIndex FreshIndex
newIdx = m () -> StateT s m ()
forall (m :: * -> *) a. Monad m => m a -> StateT s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> StateT s m ()) -> m () -> StateT s m ()
forall a b. (a -> b) -> a -> b
$ FreshIndex -> m ()
forall (m :: * -> *). MonadFresh m => FreshIndex -> m ()
setFreshIndex FreshIndex
newIdx
  getIdentifier :: StateT s m Identifier
getIdentifier = m Identifier -> StateT s m Identifier
forall (m :: * -> *) a. Monad m => m a -> StateT s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m Identifier
forall (m :: * -> *). MonadFresh m => m Identifier
getIdentifier
  localIdentifier :: forall a.
(Identifier -> Identifier) -> StateT s m a -> StateT s m a
localIdentifier Identifier -> Identifier
f (StateLazy.StateT s -> m (a, s)
m) =
    (s -> m (a, s)) -> StateT s m a
forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateLazy.StateT ((s -> m (a, s)) -> StateT s m a)
-> (s -> m (a, s)) -> StateT s m a
forall a b. (a -> b) -> a -> b
$ \s
s -> (Identifier -> Identifier) -> m (a, s) -> m (a, s)
forall a. (Identifier -> Identifier) -> m a -> m a
forall (m :: * -> *) a.
MonadFresh m =>
(Identifier -> Identifier) -> m a -> m a
localIdentifier Identifier -> Identifier
f (s -> m (a, s)
m s
s)

instance (MonadFresh m) => MonadFresh (StateStrict.StateT s m) where
  getFreshIndex :: StateT s m FreshIndex
getFreshIndex = m FreshIndex -> StateT s m FreshIndex
forall (m :: * -> *) a. Monad m => m a -> StateT s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m FreshIndex
forall (m :: * -> *). MonadFresh m => m FreshIndex
getFreshIndex
  setFreshIndex :: FreshIndex -> StateT s m ()
setFreshIndex FreshIndex
newIdx = m () -> StateT s m ()
forall (m :: * -> *) a. Monad m => m a -> StateT s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> StateT s m ()) -> m () -> StateT s m ()
forall a b. (a -> b) -> a -> b
$ FreshIndex -> m ()
forall (m :: * -> *). MonadFresh m => FreshIndex -> m ()
setFreshIndex FreshIndex
newIdx
  getIdentifier :: StateT s m Identifier
getIdentifier = m Identifier -> StateT s m Identifier
forall (m :: * -> *) a. Monad m => m a -> StateT s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m Identifier
forall (m :: * -> *). MonadFresh m => m Identifier
getIdentifier
  localIdentifier :: forall a.
(Identifier -> Identifier) -> StateT s m a -> StateT s m a
localIdentifier Identifier -> Identifier
f (StateStrict.StateT s -> m (a, s)
m) =
    (s -> m (a, s)) -> StateT s m a
forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateStrict.StateT ((s -> m (a, s)) -> StateT s m a)
-> (s -> m (a, s)) -> StateT s m a
forall a b. (a -> b) -> a -> b
$ \s
s -> (Identifier -> Identifier) -> m (a, s) -> m (a, s)
forall a. (Identifier -> Identifier) -> m a -> m a
forall (m :: * -> *) a.
MonadFresh m =>
(Identifier -> Identifier) -> m a -> m a
localIdentifier Identifier -> Identifier
f (s -> m (a, s)
m s
s)

instance (MonadFresh m) => MonadFresh (ReaderT r m) where
  getFreshIndex :: ReaderT r m FreshIndex
getFreshIndex = m FreshIndex -> ReaderT r m FreshIndex
forall (m :: * -> *) a. Monad m => m a -> ReaderT r m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m FreshIndex
forall (m :: * -> *). MonadFresh m => m FreshIndex
getFreshIndex
  setFreshIndex :: FreshIndex -> ReaderT r m ()
setFreshIndex FreshIndex
newIdx = m () -> ReaderT r m ()
forall (m :: * -> *) a. Monad m => m a -> ReaderT r m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> ReaderT r m ()) -> m () -> ReaderT r m ()
forall a b. (a -> b) -> a -> b
$ FreshIndex -> m ()
forall (m :: * -> *). MonadFresh m => FreshIndex -> m ()
setFreshIndex FreshIndex
newIdx
  getIdentifier :: ReaderT r m Identifier
getIdentifier = m Identifier -> ReaderT r m Identifier
forall (m :: * -> *) a. Monad m => m a -> ReaderT r m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m Identifier
forall (m :: * -> *). MonadFresh m => m Identifier
getIdentifier
  localIdentifier :: forall a.
(Identifier -> Identifier) -> ReaderT r m a -> ReaderT r m a
localIdentifier Identifier -> Identifier
f (ReaderT r -> m a
m) = (r -> m a) -> ReaderT r m a
forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT ((r -> m a) -> ReaderT r m a) -> (r -> m a) -> ReaderT r m a
forall a b. (a -> b) -> a -> b
$ (Identifier -> Identifier) -> m a -> m a
forall a. (Identifier -> Identifier) -> m a -> m a
forall (m :: * -> *) a.
MonadFresh m =>
(Identifier -> Identifier) -> m a -> m a
localIdentifier Identifier -> Identifier
f (m a -> m a) -> (r -> m a) -> r -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. r -> m a
m

instance (MonadFresh m, Monoid w) => MonadFresh (RWSLazy.RWST r w s m) where
  getFreshIndex :: RWST r w s m FreshIndex
getFreshIndex = m FreshIndex -> RWST r w s m FreshIndex
forall (m :: * -> *) a. Monad m => m a -> RWST r w s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m FreshIndex
forall (m :: * -> *). MonadFresh m => m FreshIndex
getFreshIndex
  setFreshIndex :: FreshIndex -> RWST r w s m ()
setFreshIndex FreshIndex
newIdx = m () -> RWST r w s m ()
forall (m :: * -> *) a. Monad m => m a -> RWST r w s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> RWST r w s m ()) -> m () -> RWST r w s m ()
forall a b. (a -> b) -> a -> b
$ FreshIndex -> m ()
forall (m :: * -> *). MonadFresh m => FreshIndex -> m ()
setFreshIndex FreshIndex
newIdx
  getIdentifier :: RWST r w s m Identifier
getIdentifier = m Identifier -> RWST r w s m Identifier
forall (m :: * -> *) a. Monad m => m a -> RWST r w s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m Identifier
forall (m :: * -> *). MonadFresh m => m Identifier
getIdentifier
  localIdentifier :: forall a.
(Identifier -> Identifier) -> RWST r w s m a -> RWST r w s m a
localIdentifier Identifier -> Identifier
f (RWSLazy.RWST r -> s -> m (a, s, w)
m) =
    (r -> s -> m (a, s, w)) -> RWST r w s m a
forall r w s (m :: * -> *) a.
(r -> s -> m (a, s, w)) -> RWST r w s m a
RWSLazy.RWST ((r -> s -> m (a, s, w)) -> RWST r w s m a)
-> (r -> s -> m (a, s, w)) -> RWST r w s m a
forall a b. (a -> b) -> a -> b
$ \r
r s
s -> (Identifier -> Identifier) -> m (a, s, w) -> m (a, s, w)
forall a. (Identifier -> Identifier) -> m a -> m a
forall (m :: * -> *) a.
MonadFresh m =>
(Identifier -> Identifier) -> m a -> m a
localIdentifier Identifier -> Identifier
f (r -> s -> m (a, s, w)
m r
r s
s)

instance (MonadFresh m, Monoid w) => MonadFresh (RWSStrict.RWST r w s m) where
  getFreshIndex :: RWST r w s m FreshIndex
getFreshIndex = m FreshIndex -> RWST r w s m FreshIndex
forall (m :: * -> *) a. Monad m => m a -> RWST r w s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m FreshIndex
forall (m :: * -> *). MonadFresh m => m FreshIndex
getFreshIndex
  setFreshIndex :: FreshIndex -> RWST r w s m ()
setFreshIndex FreshIndex
newIdx = m () -> RWST r w s m ()
forall (m :: * -> *) a. Monad m => m a -> RWST r w s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (m () -> RWST r w s m ()) -> m () -> RWST r w s m ()
forall a b. (a -> b) -> a -> b
$ FreshIndex -> m ()
forall (m :: * -> *). MonadFresh m => FreshIndex -> m ()
setFreshIndex FreshIndex
newIdx
  getIdentifier :: RWST r w s m Identifier
getIdentifier = m Identifier -> RWST r w s m Identifier
forall (m :: * -> *) a. Monad m => m a -> RWST r w s m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift m Identifier
forall (m :: * -> *). MonadFresh m => m Identifier
getIdentifier
  localIdentifier :: forall a.
(Identifier -> Identifier) -> RWST r w s m a -> RWST r w s m a
localIdentifier Identifier -> Identifier
f (RWSStrict.RWST r -> s -> m (a, s, w)
m) =
    (r -> s -> m (a, s, w)) -> RWST r w s m a
forall r w s (m :: * -> *) a.
(r -> s -> m (a, s, w)) -> RWST r w s m a
RWSStrict.RWST ((r -> s -> m (a, s, w)) -> RWST r w s m a)
-> (r -> s -> m (a, s, w)) -> RWST r w s m a
forall a b. (a -> b) -> a -> b
$ \r
r s
s -> (Identifier -> Identifier) -> m (a, s, w) -> m (a, s, w)
forall a. (Identifier -> Identifier) -> m a -> m a
forall (m :: * -> *) a.
MonadFresh m =>
(Identifier -> Identifier) -> m a -> m a
localIdentifier Identifier -> Identifier
f (r -> s -> m (a, s, w)
m r
r s
s)

-- | t'FreshT' specialized with Identity.
type Fresh = FreshT Identity

-- | Run the symbolic generation with the given identifier and 0 as the initial
-- index.
runFresh :: Fresh a -> Identifier -> a
runFresh :: forall a. Fresh a -> Identifier -> a
runFresh Fresh a
m Identifier
ident = Identity a -> a
forall a. Identity a -> a
runIdentity (Identity a -> a) -> Identity a -> a
forall a b. (a -> b) -> a -> b
$ Fresh a -> Identifier -> Identity a
forall (m :: * -> *) a. Monad m => FreshT m a -> Identifier -> m a
runFreshT Fresh a
m Identifier
ident

instance (Monad m) => MonadFresh (FreshT m) where
  getFreshIndex :: FreshT m FreshIndex
getFreshIndex = (Identifier -> FreshIndex -> m (FreshIndex, FreshIndex))
-> FreshT m FreshIndex
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m (FreshIndex, FreshIndex))
 -> FreshT m FreshIndex)
-> (Identifier -> FreshIndex -> m (FreshIndex, FreshIndex))
-> FreshT m FreshIndex
forall a b. (a -> b) -> a -> b
$ \Identifier
_ FreshIndex
idx -> (FreshIndex, FreshIndex) -> m (FreshIndex, FreshIndex)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (FreshIndex
idx, FreshIndex
idx)
  setFreshIndex :: FreshIndex -> FreshT m ()
setFreshIndex FreshIndex
newIdx = (Identifier -> FreshIndex -> m ((), FreshIndex)) -> FreshT m ()
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m ((), FreshIndex)) -> FreshT m ())
-> (Identifier -> FreshIndex -> m ((), FreshIndex)) -> FreshT m ()
forall a b. (a -> b) -> a -> b
$ \Identifier
_ FreshIndex
_ -> ((), FreshIndex) -> m ((), FreshIndex)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ((), FreshIndex
newIdx)
  getIdentifier :: FreshT m Identifier
getIdentifier = (Identifier -> FreshIndex -> m (Identifier, FreshIndex))
-> FreshT m Identifier
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m (Identifier, FreshIndex))
 -> FreshT m Identifier)
-> (Identifier -> FreshIndex -> m (Identifier, FreshIndex))
-> FreshT m Identifier
forall a b. (a -> b) -> a -> b
$ ((Identifier, FreshIndex) -> m (Identifier, FreshIndex))
-> Identifier -> FreshIndex -> m (Identifier, FreshIndex)
forall a b c. ((a, b) -> c) -> a -> b -> c
curry (Identifier, FreshIndex) -> m (Identifier, FreshIndex)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return
  localIdentifier :: forall a. (Identifier -> Identifier) -> FreshT m a -> FreshT m a
localIdentifier Identifier -> Identifier
f (FreshT Identifier -> FreshIndex -> m (a, FreshIndex)
m) = (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (Identifier -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall a b. (a -> b) -> a -> b
$ \Identifier
ident FreshIndex
idx -> do
    let newIdent :: Identifier
newIdent = Identifier -> Identifier
f Identifier
ident
    (r, _) <- Identifier -> FreshIndex -> m (a, FreshIndex)
m Identifier
newIdent FreshIndex
0
    return (r, idx)

-- | Class of types in which symbolic values can be generated with respect to
-- some specification.
--
-- The result will be wrapped in a union-like monad.
-- This ensures that we can generate those types with complex merging rules.
--
-- The uniqueness of symbolic constants is managed with the a monadic context.
-- 'Fresh' and t'FreshT' can be useful.
class (Mergeable a) => GenSym spec a where
  -- | Generate a symbolic value given some specification. Within a single
  -- `MonadFresh` context, calls to `fresh` would generate unique symbolic
  -- constants.
  --
  -- The following example generates a symbolic boolean. No specification is
  -- needed.
  --
  -- >>> runFresh (fresh ()) "a" :: Union SymBool
  -- {a@0}
  --
  -- The following example generates booleans, which cannot be merged into a
  -- single value with type 'Bool'. No specification is needed.
  --
  -- >>> runFresh (fresh ()) "a" :: Union Bool
  -- {If a@0 False True}
  --
  -- The following example generates @Maybe Bool@s.
  -- There are more than one symbolic constants introduced, and their uniqueness
  -- is ensured. No specification is needed.
  --
  -- >>> runFresh (fresh ()) "a" :: Union (Maybe Bool)
  -- {If a@0 Nothing (If a@1 (Just False) (Just True))}
  --
  -- The following example generates lists of symbolic booleans with length 1 to 2.
  --
  -- >>> runFresh (fresh (ListSpec 1 2 ())) "a" :: Union [SymBool]
  -- {If a@2 [a@1] [a@0,a@1]}
  --
  -- When multiple symbolic values are generated, there will not be any
  -- identifier collision
  --
  -- >>> runFresh (do; a <- fresh (); b <- fresh (); return (a, b)) "a" :: (Union SymBool, Union SymBool)
  -- ({a@0},{a@1})
  fresh ::
    (MonadFresh m) =>
    spec ->
    m (Union a)
  default fresh ::
    (GenSymSimple spec a) =>
    (MonadFresh m) =>
    spec ->
    m (Union a)
  fresh spec
spec = a -> Union a
forall (m :: * -> *) a.
(TryMerge m, Applicative m, Mergeable a) =>
a -> m a
mrgSingle (a -> Union a) -> m a -> m (Union a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> spec -> m a
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => spec -> m a
simpleFresh spec
spec

-- | Generate a symbolic variable wrapped in a Union without the monadic context.
-- A globally unique identifier should be supplied to ensure the uniqueness of
-- symbolic constants in the generated symbolic values.
--
-- >>> genSym (ListSpec 1 2 ()) "a" :: Union [SymBool]
-- {If a@2 [a@1] [a@0,a@1]}
genSym :: (GenSym spec a) => spec -> Identifier -> Union a
genSym :: forall spec a. GenSym spec a => spec -> Identifier -> Union a
genSym = Fresh (Union a) -> Identifier -> Union a
forall a. Fresh a -> Identifier -> a
runFresh (Fresh (Union a) -> Identifier -> Union a)
-> (spec -> Fresh (Union a)) -> spec -> Identifier -> Union a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. spec -> Fresh (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => spec -> m (Union a)
fresh

-- | Class of types in which symbolic values can be generated with respect to some specification.
--
-- The result will __/not/__ be wrapped in a union-like monad.
--
-- The uniqueness of symbolic constants is managed with the a monadic context.
-- 'Fresh' and t'FreshT' can be useful.
class GenSymSimple spec a where
  -- | Generate a symbolic value given some specification. The uniqueness is ensured.
  --
  -- The following example generates a symbolic boolean. No specification is needed.
  --
  -- >>> runFresh (simpleFresh ()) "a" :: SymBool
  -- a@0
  --
  -- The following code generates list of symbolic boolean with length 2.
  -- As the length is fixed, we don't have to wrap the result in unions.
  --
  -- >>> runFresh (simpleFresh (SimpleListSpec 2 ())) "a" :: [SymBool]
  -- [a@0,a@1]
  simpleFresh ::
    (MonadFresh m) =>
    spec ->
    m a

-- | Generate a simple symbolic variable wrapped in a Union without the monadic context.
-- A globally unique identifier should be supplied to ensure the uniqueness of
-- symbolic constants in the generated symbolic values.
--
-- >>> genSymSimple (SimpleListSpec 2 ()) "a" :: [SymBool]
-- [a@0,a@1]
genSymSimple :: forall spec a. (GenSymSimple spec a) => spec -> Identifier -> a
genSymSimple :: forall spec a. GenSymSimple spec a => spec -> Identifier -> a
genSymSimple = Fresh a -> Identifier -> a
forall a. Fresh a -> Identifier -> a
runFresh (Fresh a -> Identifier -> a)
-> (spec -> Fresh a) -> spec -> Identifier -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. spec -> Fresh a
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => spec -> m a
simpleFresh

class GenSymNoSpec a where
  freshNoSpec ::
    (MonadFresh m) =>
    m (Union (a c))

instance GenSymNoSpec U1 where
  freshNoSpec :: forall (m :: * -> *) c. MonadFresh m => m (Union (U1 c))
freshNoSpec = Union (U1 c) -> m (Union (U1 c))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Union (U1 c) -> m (Union (U1 c)))
-> Union (U1 c) -> m (Union (U1 c))
forall a b. (a -> b) -> a -> b
$ U1 c -> Union (U1 c)
forall (m :: * -> *) a.
(TryMerge m, Applicative m, Mergeable a) =>
a -> m a
mrgSingle U1 c
forall k (p :: k). U1 p
U1

instance (GenSym () c) => GenSymNoSpec (K1 i c) where
  freshNoSpec :: forall (m :: * -> *) c. MonadFresh m => m (Union (K1 i c c))
freshNoSpec = (c -> K1 i c c) -> Union c -> Union (K1 i c c)
forall a b. (a -> b) -> Union a -> Union b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap c -> K1 i c c
forall k i c (p :: k). c -> K1 i c p
K1 (Union c -> Union (K1 i c c))
-> m (Union c) -> m (Union (K1 i c c))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> () -> m (Union c)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => () -> m (Union c)
fresh ()

instance (GenSymNoSpec a) => GenSymNoSpec (M1 i c a) where
  freshNoSpec :: forall (m :: * -> *) c. MonadFresh m => m (Union (M1 i c a c))
freshNoSpec = (a c -> M1 i c a c) -> Union (a c) -> Union (M1 i c a c)
forall a b. (a -> b) -> Union a -> Union b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a c -> M1 i c a c
forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 (Union (a c) -> Union (M1 i c a c))
-> m (Union (a c)) -> m (Union (M1 i c a c))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Union (a c))
forall (a :: * -> *) (m :: * -> *) c.
(GenSymNoSpec a, MonadFresh m) =>
m (Union (a c))
forall (m :: * -> *) c. MonadFresh m => m (Union (a c))
freshNoSpec

instance
  ( GenSymNoSpec a,
    GenSymNoSpec b,
    forall x. Mergeable (a x),
    forall x. Mergeable (b x)
  ) =>
  GenSymNoSpec (a :+: b)
  where
  freshNoSpec ::
    forall m c.
    (MonadFresh m) =>
    m (Union ((a :+: b) c))
  freshNoSpec :: forall (m :: * -> *) c. MonadFresh m => m (Union ((:+:) a b c))
freshNoSpec = do
    cond :: bool <- () -> m SymBool
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => () -> m SymBool
simpleFresh ()
    l :: Union (a c) <- freshNoSpec
    r :: Union (b c) <- freshNoSpec
    return $ mrgIf cond (fmap L1 l) (fmap R1 r)

instance
  (GenSymNoSpec a, GenSymNoSpec b) =>
  GenSymNoSpec (a :*: b)
  where
  freshNoSpec ::
    forall m c.
    (MonadFresh m) =>
    m (Union ((a :*: b) c))
  freshNoSpec :: forall (m :: * -> *) c. MonadFresh m => m (Union ((:*:) a b c))
freshNoSpec = do
    l :: Union (a c) <- m (Union (a c))
forall (a :: * -> *) (m :: * -> *) c.
(GenSymNoSpec a, MonadFresh m) =>
m (Union (a c))
forall (m :: * -> *) c. MonadFresh m => m (Union (a c))
freshNoSpec
    r :: Union (b c) <- freshNoSpec
    return $ do
      l1 <- l
      r1 <- r
      return $ l1 :*: r1

-- | We cannot provide DerivingVia style derivation for 'GenSym', while you can
-- use this 'fresh' implementation to implement 'GenSym' for your own types.
--
-- This 'fresh' implementation is for the types that does not need any specification.
-- It will generate product types by generating each fields with @()@ as specification,
-- and generate all possible values for a sum type.
--
-- __Note:__ __Never__ use on recursive types.
derivedNoSpecFresh ::
  forall a m.
  ( Generic a,
    GenSymNoSpec (Rep a),
    Mergeable a,
    MonadFresh m
  ) =>
  () ->
  m (Union a)
derivedNoSpecFresh :: forall a (m :: * -> *).
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (Union a)
derivedNoSpecFresh ()
_ = Union a -> Union a
forall (m :: * -> *) a. (TryMerge m, Mergeable a) => m a -> m a
tryMerge (Union a -> Union a)
-> (Union (Rep a Any) -> Union a) -> Union (Rep a Any) -> Union a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Rep a Any -> a) -> Union (Rep a Any) -> Union a
forall a b. (a -> b) -> Union a -> Union b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Rep a Any -> a
forall a x. Generic a => Rep a x -> a
forall x. Rep a x -> a
to (Union (Rep a Any) -> Union a)
-> m (Union (Rep a Any)) -> m (Union a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Union (Rep a Any))
forall (a :: * -> *) (m :: * -> *) c.
(GenSymNoSpec a, MonadFresh m) =>
m (Union (a c))
forall (m :: * -> *) c. MonadFresh m => m (Union (Rep a c))
freshNoSpec

class GenSymSimpleNoSpec a where
  simpleFreshNoSpec :: (MonadFresh m) => m (a c)

instance GenSymSimpleNoSpec U1 where
  simpleFreshNoSpec :: forall (m :: * -> *) c. MonadFresh m => m (U1 c)
simpleFreshNoSpec = U1 c -> m (U1 c)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return U1 c
forall k (p :: k). U1 p
U1

instance (GenSymSimple () c) => GenSymSimpleNoSpec (K1 i c) where
  simpleFreshNoSpec :: forall (m :: * -> *) c. MonadFresh m => m (K1 i c c)
simpleFreshNoSpec = c -> K1 i c c
forall k i c (p :: k). c -> K1 i c p
K1 (c -> K1 i c c) -> m c -> m (K1 i c c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> () -> m c
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => () -> m c
simpleFresh ()

instance (GenSymSimpleNoSpec a) => GenSymSimpleNoSpec (M1 i c a) where
  simpleFreshNoSpec :: forall (m :: * -> *) c. MonadFresh m => m (M1 i c a c)
simpleFreshNoSpec = a c -> M1 i c a c
forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 (a c -> M1 i c a c) -> m (a c) -> m (M1 i c a c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (a c)
forall (a :: * -> *) (m :: * -> *) c.
(GenSymSimpleNoSpec a, MonadFresh m) =>
m (a c)
forall (m :: * -> *) c. MonadFresh m => m (a c)
simpleFreshNoSpec

instance
  (GenSymSimpleNoSpec a, GenSymSimpleNoSpec b) =>
  GenSymSimpleNoSpec (a :*: b)
  where
  simpleFreshNoSpec :: forall (m :: * -> *) c. MonadFresh m => m ((:*:) a b c)
simpleFreshNoSpec = do
    l :: a c <- m (a c)
forall (a :: * -> *) (m :: * -> *) c.
(GenSymSimpleNoSpec a, MonadFresh m) =>
m (a c)
forall (m :: * -> *) c. MonadFresh m => m (a c)
simpleFreshNoSpec
    r :: b c <- simpleFreshNoSpec
    return $ l :*: r

-- | We cannot provide DerivingVia style derivation for 'GenSymSimple', while
-- you can use this 'simpleFresh' implementation to implement 'GenSymSimple' fo
-- your own types.
--
-- This 'simpleFresh' implementation is for the types that does not need any specification.
-- It will generate product types by generating each fields with @()@ as specification.
-- It will not work on sum types.
--
-- __Note:__ __Never__ use on recursive types.
derivedNoSpecSimpleFresh ::
  forall a m.
  ( Generic a,
    GenSymSimpleNoSpec (Rep a),
    MonadFresh m
  ) =>
  () ->
  m a
derivedNoSpecSimpleFresh :: forall a (m :: * -> *).
(Generic a, GenSymSimpleNoSpec (Rep a), MonadFresh m) =>
() -> m a
derivedNoSpecSimpleFresh ()
_ = Rep a Any -> a
forall a x. Generic a => Rep a x -> a
forall x. Rep a x -> a
to (Rep a Any -> a) -> m (Rep a Any) -> m a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Rep a Any)
forall (a :: * -> *) (m :: * -> *) c.
(GenSymSimpleNoSpec a, MonadFresh m) =>
m (a c)
forall (m :: * -> *) c. MonadFresh m => m (Rep a c)
simpleFreshNoSpec

class GenSymSameShape a where
  genSymSameShapeFresh ::
    (MonadFresh m) =>
    a c ->
    m (a c)

instance GenSymSameShape U1 where
  genSymSameShapeFresh :: forall (m :: * -> *) c. MonadFresh m => U1 c -> m (U1 c)
genSymSameShapeFresh U1 c
_ = U1 c -> m (U1 c)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return U1 c
forall k (p :: k). U1 p
U1

instance (GenSymSimple c c) => GenSymSameShape (K1 i c) where
  genSymSameShapeFresh :: forall (m :: * -> *) c. MonadFresh m => K1 i c c -> m (K1 i c c)
genSymSameShapeFresh (K1 c
c) = c -> K1 i c c
forall k i c (p :: k). c -> K1 i c p
K1 (c -> K1 i c c) -> m c -> m (K1 i c c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> c -> m c
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => c -> m c
simpleFresh c
c

instance (GenSymSameShape a) => GenSymSameShape (M1 i c a) where
  genSymSameShapeFresh :: forall (m :: * -> *) c.
MonadFresh m =>
M1 i c a c -> m (M1 i c a c)
genSymSameShapeFresh (M1 a c
a) = a c -> M1 i c a c
forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 (a c -> M1 i c a c) -> m (a c) -> m (M1 i c a c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a c -> m (a c)
forall (a :: * -> *) (m :: * -> *) c.
(GenSymSameShape a, MonadFresh m) =>
a c -> m (a c)
forall (m :: * -> *) c. MonadFresh m => a c -> m (a c)
genSymSameShapeFresh a c
a

instance
  (GenSymSameShape a, GenSymSameShape b) =>
  GenSymSameShape (a :+: b)
  where
  genSymSameShapeFresh :: forall (m :: * -> *) c.
MonadFresh m =>
(:+:) a b c -> m ((:+:) a b c)
genSymSameShapeFresh (L1 a c
a) = a c -> (:+:) a b c
forall k (f :: k -> *) (g :: k -> *) (p :: k). f p -> (:+:) f g p
L1 (a c -> (:+:) a b c) -> m (a c) -> m ((:+:) a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> a c -> m (a c)
forall (a :: * -> *) (m :: * -> *) c.
(GenSymSameShape a, MonadFresh m) =>
a c -> m (a c)
forall (m :: * -> *) c. MonadFresh m => a c -> m (a c)
genSymSameShapeFresh a c
a
  genSymSameShapeFresh (R1 b c
a) = b c -> (:+:) a b c
forall k (f :: k -> *) (g :: k -> *) (p :: k). g p -> (:+:) f g p
R1 (b c -> (:+:) a b c) -> m (b c) -> m ((:+:) a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> b c -> m (b c)
forall (a :: * -> *) (m :: * -> *) c.
(GenSymSameShape a, MonadFresh m) =>
a c -> m (a c)
forall (m :: * -> *) c. MonadFresh m => b c -> m (b c)
genSymSameShapeFresh b c
a

instance
  (GenSymSameShape a, GenSymSameShape b) =>
  GenSymSameShape (a :*: b)
  where
  genSymSameShapeFresh :: forall (m :: * -> *) c.
MonadFresh m =>
(:*:) a b c -> m ((:*:) a b c)
genSymSameShapeFresh (a c
a :*: b c
b) = do
    l :: a c <- a c -> m (a c)
forall (a :: * -> *) (m :: * -> *) c.
(GenSymSameShape a, MonadFresh m) =>
a c -> m (a c)
forall (m :: * -> *) c. MonadFresh m => a c -> m (a c)
genSymSameShapeFresh a c
a
    r :: b c <- genSymSameShapeFresh b
    return $ l :*: r

-- | We cannot provide DerivingVia style derivation for 'GenSymSimple', while
-- you can use this 'simpleFresh' implementation to implement 'GenSymSimple' fo
-- your own types.
--
-- This 'simpleFresh' implementation is for the types that can be generated with
-- a reference value of the same type.
--
-- For sum types, it will generate the result with the same data constructor.
-- For product types, it will generate the result by generating each field with
-- the corresponding reference value.
--
-- __Note:__ __Can__ be used on recursive types.
derivedSameShapeSimpleFresh ::
  forall a m.
  ( Generic a,
    GenSymSameShape (Rep a),
    MonadFresh m
  ) =>
  a ->
  m a
derivedSameShapeSimpleFresh :: forall a (m :: * -> *).
(Generic a, GenSymSameShape (Rep a), MonadFresh m) =>
a -> m a
derivedSameShapeSimpleFresh a
a = Rep a Any -> a
forall a x. Generic a => Rep a x -> a
forall x. Rep a x -> a
to (Rep a Any -> a) -> m (Rep a Any) -> m a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Rep a Any -> m (Rep a Any)
forall (a :: * -> *) (m :: * -> *) c.
(GenSymSameShape a, MonadFresh m) =>
a c -> m (a c)
forall (m :: * -> *) c. MonadFresh m => Rep a c -> m (Rep a c)
genSymSameShapeFresh (a -> Rep a Any
forall x. a -> Rep a x
forall a x. Generic a => a -> Rep a x
from a
a)

genGuardsUnion :: (MonadFresh m, Mergeable a) => [Union a] -> m (Union a)
genGuardsUnion :: forall (m :: * -> *) a.
(MonadFresh m, Mergeable a) =>
[Union a] -> m (Union a)
genGuardsUnion [Union a
x] = Union a -> m (Union a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Union a
x
genGuardsUnion (Union a
r : [Union a]
rs) = do
  b <- () -> m SymBool
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => () -> m SymBool
simpleFresh ()
  res <- genGuardsUnion rs
  return $ mrgIf b r res
genGuardsUnion [] = String -> m (Union a)
forall a. HasCallStack => String -> a
error String
"chooseFresh expects at least one value"

genGuards :: (MonadFresh m, Mergeable a) => [a] -> m (Union a)
genGuards :: forall (m :: * -> *) a.
(MonadFresh m, Mergeable a) =>
[a] -> m (Union a)
genGuards [a
x] = Union a -> m (Union a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Union a -> m (Union a)) -> Union a -> m (Union a)
forall a b. (a -> b) -> a -> b
$ a -> Union a
forall (m :: * -> *) a.
(TryMerge m, Applicative m, Mergeable a) =>
a -> m a
mrgSingle a
x
genGuards (a
r : [a]
rs) = do
  b <- () -> m SymBool
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => () -> m SymBool
simpleFresh ()
  res <- genGuards rs
  return $ mrgIf b (mrgSingle r) res
genGuards [] = String -> m (Union a)
forall a. HasCallStack => String -> a
error String
"chooseFresh expects at least one value"

genGuardsSimple :: (MonadFresh m, SimpleMergeable a) => [a] -> m a
genGuardsSimple :: forall (m :: * -> *) a.
(MonadFresh m, SimpleMergeable a) =>
[a] -> m a
genGuardsSimple [a
x] = a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x
genGuardsSimple (a
r : [a]
rs) = do
  b <- () -> m SymBool
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => () -> m SymBool
simpleFresh ()
  res <- genGuardsSimple rs
  return $ mrgIte b r res
genGuardsSimple [] = String -> m a
forall a. HasCallStack => String -> a
error String
"chooseFresh expects at least one value"

leveledChoose ::
  (Monad m, Mergeable b1) =>
  ([b2] -> m b2) -> ([b1] -> m b2) -> [b1] -> m b2
leveledChoose :: forall (m :: * -> *) b1 b2.
(Monad m, Mergeable b1) =>
([b2] -> m b2) -> ([b1] -> m b2) -> [b1] -> m b2
leveledChoose [b2] -> m b2
gen [b1] -> m b2
gen' [b1]
l = Int -> [(b1, [DynamicSortedIdx])] -> m b2
go Int
0 [(b1, [DynamicSortedIdx])]
choicesWithIndices
  where
    indices :: [[DynamicSortedIdx]]
indices = b1 -> [DynamicSortedIdx]
forall a. Mergeable a => a -> [DynamicSortedIdx]
sortIndices (b1 -> [DynamicSortedIdx]) -> [b1] -> [[DynamicSortedIdx]]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [b1]
l
    choicesWithIndices :: [(b1, [DynamicSortedIdx])]
choicesWithIndices = ((b1, [DynamicSortedIdx]) -> [DynamicSortedIdx])
-> [(b1, [DynamicSortedIdx])] -> [(b1, [DynamicSortedIdx])]
forall b a. Ord b => (a -> b) -> [a] -> [a]
sortOn (b1, [DynamicSortedIdx]) -> [DynamicSortedIdx]
forall a b. (a, b) -> b
snd ([(b1, [DynamicSortedIdx])] -> [(b1, [DynamicSortedIdx])])
-> [(b1, [DynamicSortedIdx])] -> [(b1, [DynamicSortedIdx])]
forall a b. (a -> b) -> a -> b
$ [b1] -> [[DynamicSortedIdx]] -> [(b1, [DynamicSortedIdx])]
forall a b. [a] -> [b] -> [(a, b)]
zip [b1]
l [[DynamicSortedIdx]]
indices
    go :: Int -> [(b1, [DynamicSortedIdx])] -> m b2
go Int
i [(b1, [DynamicSortedIdx])]
l = do
      let grouped :: [[(b1, [DynamicSortedIdx])]]
grouped =
            ((b1, [DynamicSortedIdx]) -> (b1, [DynamicSortedIdx]) -> Bool)
-> [(b1, [DynamicSortedIdx])] -> [[(b1, [DynamicSortedIdx])]]
forall a. (a -> a -> Bool) -> [a] -> [[a]]
groupBy
              ( \(b1
_, [DynamicSortedIdx]
a) (b1
_, [DynamicSortedIdx]
b) ->
                  ([DynamicSortedIdx] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [DynamicSortedIdx]
a Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
i Bool -> Bool -> Bool
&& [DynamicSortedIdx] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [DynamicSortedIdx]
b Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
i) Bool -> Bool -> Bool
|| [DynamicSortedIdx]
a [DynamicSortedIdx] -> Int -> DynamicSortedIdx
forall a. HasCallStack => [a] -> Int -> a
!! Int
i DynamicSortedIdx -> DynamicSortedIdx -> Bool
forall a. Eq a => a -> a -> Bool
== [DynamicSortedIdx]
b [DynamicSortedIdx] -> Int -> DynamicSortedIdx
forall a. HasCallStack => [a] -> Int -> a
!! Int
i
              )
              [(b1, [DynamicSortedIdx])]
l
      allChoices <- ([(b1, [DynamicSortedIdx])] -> m b2)
-> [[(b1, [DynamicSortedIdx])]] -> m [b2]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse (Int -> [(b1, [DynamicSortedIdx])] -> m b2
go' Int
i) [[(b1, [DynamicSortedIdx])]]
grouped
      gen allChoices
    go' :: Int -> [(b1, [DynamicSortedIdx])] -> m b2
go' Int
i [(b1, [DynamicSortedIdx])]
l =
      if [DynamicSortedIdx] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ((b1, [DynamicSortedIdx]) -> [DynamicSortedIdx]
forall a b. (a, b) -> b
snd ((b1, [DynamicSortedIdx]) -> [DynamicSortedIdx])
-> (b1, [DynamicSortedIdx]) -> [DynamicSortedIdx]
forall a b. (a -> b) -> a -> b
$ [(b1, [DynamicSortedIdx])] -> (b1, [DynamicSortedIdx])
forall a. HasCallStack => [a] -> a
head [(b1, [DynamicSortedIdx])]
l) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
i
        then [b1] -> m b2
gen' ([b1] -> m b2) -> [b1] -> m b2
forall a b. (a -> b) -> a -> b
$ (b1, [DynamicSortedIdx]) -> b1
forall a b. (a, b) -> a
fst ((b1, [DynamicSortedIdx]) -> b1)
-> [(b1, [DynamicSortedIdx])] -> [b1]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(b1, [DynamicSortedIdx])]
l
        else Int -> [(b1, [DynamicSortedIdx])] -> m b2
go (Int
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) [(b1, [DynamicSortedIdx])]
l

-- | Symbolically chooses one of the provided values.
-- The procedure creates @n - 1@ fresh symbolic boolean variables every time it
-- is evaluated, and use these variables to conditionally select one of the @n@
-- provided expressions.
--
-- The result will be wrapped in a union-like monad, and also a monad
-- maintaining the 'MonadFresh' context.
--
-- >>> runFresh (chooseFresh [1,2,3]) "a" :: Union Integer
-- {If a@0 1 (If a@1 2 3)}
chooseFresh ::
  forall a m.
  ( Mergeable a,
    MonadFresh m
  ) =>
  [a] ->
  m (Union a)
chooseFresh :: forall a (m :: * -> *).
(Mergeable a, MonadFresh m) =>
[a] -> m (Union a)
chooseFresh = ([Union a] -> m (Union a))
-> ([a] -> m (Union a)) -> [a] -> m (Union a)
forall (m :: * -> *) b1 b2.
(Monad m, Mergeable b1) =>
([b2] -> m b2) -> ([b1] -> m b2) -> [b1] -> m b2
leveledChoose [Union a] -> m (Union a)
forall (m :: * -> *) a.
(MonadFresh m, Mergeable a) =>
[Union a] -> m (Union a)
genGuardsUnion [a] -> m (Union a)
forall (m :: * -> *) a.
(MonadFresh m, Mergeable a) =>
[a] -> m (Union a)
genGuards

-- | A wrapper for `chooseFresh` that executes the `MonadFresh` context.
-- A globally unique identifier should be supplied to ensure the uniqueness of
-- symbolic constants in the generated symbolic values.
choose ::
  forall a.
  (Mergeable a) =>
  [a] ->
  Identifier ->
  Union a
choose :: forall a. Mergeable a => [a] -> Identifier -> Union a
choose = Fresh (Union a) -> Identifier -> Union a
forall a. Fresh a -> Identifier -> a
runFresh (Fresh (Union a) -> Identifier -> Union a)
-> ([a] -> Fresh (Union a)) -> [a] -> Identifier -> Union a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Fresh (Union a)
forall a (m :: * -> *).
(Mergeable a, MonadFresh m) =>
[a] -> m (Union a)
chooseFresh

-- | Symbolically chooses one of the provided values.
-- The procedure creates @n - 1@ fresh symbolic boolean variables every time it is evaluated, and use
-- these variables to conditionally select one of the @n@ provided expressions.
--
-- The result will __/not/__ be wrapped in a union-like monad, but will be
-- wrapped in a monad maintaining the 'Fresh' context.
--
-- >>> import Data.Proxy
-- >>> runFresh (chooseSimpleFresh [ssym "b", ssym "c", ssym "d"]) "a" :: SymInteger
-- (ite a@0 b (ite a@1 c d))
chooseSimpleFresh ::
  forall a m.
  ( SimpleMergeable a,
    MonadFresh m
  ) =>
  [a] ->
  m a
chooseSimpleFresh :: forall a (m :: * -> *).
(SimpleMergeable a, MonadFresh m) =>
[a] -> m a
chooseSimpleFresh = ([a] -> m a) -> ([a] -> m a) -> [a] -> m a
forall (m :: * -> *) b1 b2.
(Monad m, Mergeable b1) =>
([b2] -> m b2) -> ([b1] -> m b2) -> [b1] -> m b2
leveledChoose [a] -> m a
forall (m :: * -> *) a.
(MonadFresh m, SimpleMergeable a) =>
[a] -> m a
genGuardsSimple [a] -> m a
forall (m :: * -> *) a.
(MonadFresh m, SimpleMergeable a) =>
[a] -> m a
genGuardsSimple

-- | A wrapper for `chooseSimpleFresh` that executes the `MonadFresh` context.
-- A globally unique identifier should be supplied to ensure the uniqueness of
-- symbolic constants in the generated symbolic values.
chooseSimple ::
  forall a.
  (SimpleMergeable a) =>
  [a] ->
  Identifier ->
  a
chooseSimple :: forall a. SimpleMergeable a => [a] -> Identifier -> a
chooseSimple = Fresh a -> Identifier -> a
forall a. Fresh a -> Identifier -> a
runFresh (Fresh a -> Identifier -> a)
-> ([a] -> Fresh a) -> [a] -> Identifier -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Fresh a
forall a (m :: * -> *).
(SimpleMergeable a, MonadFresh m) =>
[a] -> m a
chooseSimpleFresh

-- | Symbolically chooses one of the provided values wrapped in union-like
-- monads. The procedure creates @n - 1@ fresh symbolic boolean variables every
-- time it is evaluated, and use these variables to conditionally select one of
-- the @n@ provided expressions.
--
-- The result will be wrapped in a union-like monad, and also a monad
-- maintaining the 'Fresh' context.
--
-- >>> let a = runFresh (chooseFresh [1, 2]) "a" :: Union Integer
-- >>> let b = runFresh (chooseFresh [2, 3]) "b" :: Union Integer
-- >>> runFresh (chooseUnionFresh [a, b]) "c" :: Union Integer
-- {If (&& c@0 a@0) 1 (If (|| c@0 b@0) 2 3)}
chooseUnionFresh ::
  forall a m.
  ( Mergeable a,
    MonadFresh m
  ) =>
  [Union a] ->
  m (Union a)
chooseUnionFresh :: forall a (m :: * -> *).
(Mergeable a, MonadFresh m) =>
[Union a] -> m (Union a)
chooseUnionFresh = ([Union a] -> m (Union a))
-> ([Union a] -> m (Union a)) -> [Union a] -> m (Union a)
forall (m :: * -> *) b1 b2.
(Monad m, Mergeable b1) =>
([b2] -> m b2) -> ([b1] -> m b2) -> [b1] -> m b2
leveledChoose [Union a] -> m (Union a)
forall (m :: * -> *) a.
(MonadFresh m, Mergeable a) =>
[Union a] -> m (Union a)
genGuardsUnion [Union a] -> m (Union a)
forall (m :: * -> *) a.
(MonadFresh m, Mergeable a) =>
[Union a] -> m (Union a)
genGuardsUnion

-- | A wrapper for `chooseUnionFresh` that executes the `MonadFresh` context.
-- A globally unique identifier should be supplied to ensure the uniqueness of
-- symbolic constants in the generated symbolic values.
chooseUnion ::
  forall a.
  (Mergeable a) =>
  [Union a] ->
  Identifier ->
  Union a
chooseUnion :: forall a. Mergeable a => [Union a] -> Identifier -> Union a
chooseUnion = Fresh (Union a) -> Identifier -> Union a
forall a. Fresh a -> Identifier -> a
runFresh (Fresh (Union a) -> Identifier -> Union a)
-> ([Union a] -> Fresh (Union a))
-> [Union a]
-> Identifier
-> Union a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Union a] -> Fresh (Union a)
forall a (m :: * -> *).
(Mergeable a, MonadFresh m) =>
[Union a] -> m (Union a)
chooseUnionFresh

#define CONCRETE_GENSYM_SAME_SHAPE(type) \
instance GenSym type type where fresh = return . mrgSingle

#define CONCRETE_GENSYMSIMPLE_SAME_SHAPE(type) \
instance GenSymSimple type type where simpleFresh = return

#define CONCRETE_GENSYM_SAME_SHAPE_BV(type) \
instance (KnownNat n, 1 <= n) => GenSym (type n) (type n) where fresh = return . mrgSingle

#define CONCRETE_GENSYMSIMPLE_SAME_SHAPE_BV(type) \
instance (KnownNat n, 1 <= n) => GenSymSimple (type n) (type n) where simpleFresh = return

#if 1
CONCRETE_GENSYM_SAME_SHAPE(Bool)
CONCRETE_GENSYM_SAME_SHAPE(Integer)
CONCRETE_GENSYM_SAME_SHAPE(Char)
CONCRETE_GENSYM_SAME_SHAPE(Int)
CONCRETE_GENSYM_SAME_SHAPE(Int8)
CONCRETE_GENSYM_SAME_SHAPE(Int16)
CONCRETE_GENSYM_SAME_SHAPE(Int32)
CONCRETE_GENSYM_SAME_SHAPE(Int64)
CONCRETE_GENSYM_SAME_SHAPE(Word)
CONCRETE_GENSYM_SAME_SHAPE(Word8)
CONCRETE_GENSYM_SAME_SHAPE(Word16)
CONCRETE_GENSYM_SAME_SHAPE(Word32)
CONCRETE_GENSYM_SAME_SHAPE(Word64)
CONCRETE_GENSYM_SAME_SHAPE(Float)
CONCRETE_GENSYM_SAME_SHAPE(Double)
CONCRETE_GENSYM_SAME_SHAPE(B.ByteString)
CONCRETE_GENSYM_SAME_SHAPE(T.Text)
CONCRETE_GENSYM_SAME_SHAPE(FPRoundingMode)
CONCRETE_GENSYM_SAME_SHAPE_BV(WordN)
CONCRETE_GENSYM_SAME_SHAPE_BV(IntN)

CONCRETE_GENSYMSIMPLE_SAME_SHAPE(Bool)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(Integer)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(Char)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(Int)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(Int8)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(Int16)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(Int32)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(Int64)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(Word)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(Word8)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(Word16)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(Word32)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(Word64)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(Float)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(Double)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(B.ByteString)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(T.Text)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE(FPRoundingMode)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE_BV(WordN)
CONCRETE_GENSYMSIMPLE_SAME_SHAPE_BV(IntN)
#endif

instance (Integral a, Typeable a, Show a) => GenSym (Ratio a) (Ratio a) where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
Ratio a -> m (Union (Ratio a))
fresh = Union (Ratio a) -> m (Union (Ratio a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Union (Ratio a) -> m (Union (Ratio a)))
-> (Ratio a -> Union (Ratio a)) -> Ratio a -> m (Union (Ratio a))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Ratio a -> Union (Ratio a)
forall (m :: * -> *) a.
(TryMerge m, Applicative m, Mergeable a) =>
a -> m a
mrgSingle

instance GenSymSimple (Ratio a) (Ratio a) where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => Ratio a -> m (Ratio a)
simpleFresh = Ratio a -> m (Ratio a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return

instance (ValidFP eb sb) => GenSym (FP eb sb) (FP eb sb) where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
FP eb sb -> m (Union (FP eb sb))
fresh = Union (FP eb sb) -> m (Union (FP eb sb))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Union (FP eb sb) -> m (Union (FP eb sb)))
-> (FP eb sb -> Union (FP eb sb))
-> FP eb sb
-> m (Union (FP eb sb))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FP eb sb -> Union (FP eb sb)
forall (m :: * -> *) a.
(TryMerge m, Applicative m, Mergeable a) =>
a -> m a
mrgSingle
  {-# INLINE fresh #-}

instance (ValidFP eb sb) => GenSymSimple (FP eb sb) (FP eb sb) where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => FP eb sb -> m (FP eb sb)
simpleFresh = FP eb sb -> m (FP eb sb)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return
  {-# INLINE simpleFresh #-}

-- Bool
instance GenSym () Bool where
  fresh :: forall (m :: * -> *). MonadFresh m => () -> m (Union Bool)
fresh = () -> m (Union Bool)
forall a (m :: * -> *).
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (Union a)
derivedNoSpecFresh

-- Enums

-- | Specification for enum values with upper bound (exclusive). The result would chosen from [0 .. upperbound].
--
-- >>> runFresh (fresh (EnumGenUpperBound @Integer 4)) "c" :: Union Integer
-- {If c@0 0 (If c@1 1 (If c@2 2 3))}
newtype EnumGenUpperBound a = EnumGenUpperBound a

instance (Enum v, Mergeable v) => GenSym (EnumGenUpperBound v) v where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
EnumGenUpperBound v -> m (Union v)
fresh (EnumGenUpperBound v
u) = [v] -> m (Union v)
forall a (m :: * -> *).
(Mergeable a, MonadFresh m) =>
[a] -> m (Union a)
chooseFresh (Int -> v
forall a. Enum a => Int -> a
toEnum (Int -> v) -> [Int] -> [v]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [Int
0 .. v -> Int
forall a. Enum a => a -> Int
fromEnum v
u Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1])

-- | Specification for numbers with lower bound (inclusive) and upper bound (exclusive)
--
-- >>> runFresh (fresh (EnumGenBound @Integer 0 4)) "c" :: Union Integer
-- {If c@0 0 (If c@1 1 (If c@2 2 3))}
data EnumGenBound a = EnumGenBound a a

instance (Enum v, Mergeable v) => GenSym (EnumGenBound v) v where
  fresh :: forall (m :: * -> *). MonadFresh m => EnumGenBound v -> m (Union v)
fresh (EnumGenBound v
l v
u) = [v] -> m (Union v)
forall a (m :: * -> *).
(Mergeable a, MonadFresh m) =>
[a] -> m (Union a)
chooseFresh (Int -> v
forall a. Enum a => Int -> a
toEnum (Int -> v) -> [Int] -> [v]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [v -> Int
forall a. Enum a => a -> Int
fromEnum v
l .. v -> Int
forall a. Enum a => a -> Int
fromEnum v
u Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1])

-- Either
instance
  ( GenSym aspec a,
    Mergeable a,
    GenSym bspec b,
    Mergeable b
  ) =>
  GenSym (Either aspec bspec) (Either a b)
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
Either aspec bspec -> m (Union (Either a b))
fresh (Left aspec
aspec) = (Union (Either a b) -> Union (Either a b)
forall (m :: * -> *) a. (TryMerge m, Mergeable a) => m a -> m a
tryMerge (Union (Either a b) -> Union (Either a b))
-> (Union a -> Union (Either a b)) -> Union a -> Union (Either a b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Either a b) -> Union a -> Union (Either a b)
forall a b. (a -> b) -> Union a -> Union b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Either a b
forall a b. a -> Either a b
Left) (Union a -> Union (Either a b))
-> m (Union a) -> m (Union (Either a b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> aspec -> m (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => aspec -> m (Union a)
fresh aspec
aspec
  fresh (Right bspec
bspec) = (Union (Either a b) -> Union (Either a b)
forall (m :: * -> *) a. (TryMerge m, Mergeable a) => m a -> m a
tryMerge (Union (Either a b) -> Union (Either a b))
-> (Union b -> Union (Either a b)) -> Union b -> Union (Either a b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (b -> Either a b) -> Union b -> Union (Either a b)
forall a b. (a -> b) -> Union a -> Union b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b -> Either a b
forall a b. b -> Either a b
Right) (Union b -> Union (Either a b))
-> m (Union b) -> m (Union (Either a b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> bspec -> m (Union b)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => bspec -> m (Union b)
fresh bspec
bspec

instance
  ( GenSymSimple aspec a,
    GenSymSimple bspec b
  ) =>
  GenSymSimple (Either aspec bspec) (Either a b)
  where
  simpleFresh :: forall (m :: * -> *).
MonadFresh m =>
Either aspec bspec -> m (Either a b)
simpleFresh (Left aspec
a) = a -> Either a b
forall a b. a -> Either a b
Left (a -> Either a b) -> m a -> m (Either a b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> aspec -> m a
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => aspec -> m a
simpleFresh aspec
a
  simpleFresh (Right bspec
b) = b -> Either a b
forall a b. b -> Either a b
Right (b -> Either a b) -> m b -> m (Either a b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> bspec -> m b
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => bspec -> m b
simpleFresh bspec
b

instance
  (GenSym () a, Mergeable a, GenSym () b, Mergeable b) =>
  GenSym () (Either a b)
  where
  fresh :: forall (m :: * -> *). MonadFresh m => () -> m (Union (Either a b))
fresh = () -> m (Union (Either a b))
forall a (m :: * -> *).
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (Union a)
derivedNoSpecFresh

instance
  ( GenSym aspec a,
    Mergeable a,
    GenSym bspec b,
    Mergeable b
  ) =>
  GenSym (aspec, bspec) (Either a b)
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
(aspec, bspec) -> m (Union (Either a b))
fresh (aspec
aspec, bspec
bspec) = do
    l :: Union a <- aspec -> m (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => aspec -> m (Union a)
fresh aspec
aspec
    r :: Union b <- fresh bspec
    chooseUnionFresh [Left <$> l, Right <$> r]

-- Maybe
instance
  {-# OVERLAPPING #-}
  (GenSym aspec a, Mergeable a) =>
  GenSym (Maybe aspec) (Maybe a)
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
Maybe aspec -> m (Union (Maybe a))
fresh Maybe aspec
Nothing = Union (Maybe a) -> m (Union (Maybe a))
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Union (Maybe a) -> m (Union (Maybe a)))
-> Union (Maybe a) -> m (Union (Maybe a))
forall a b. (a -> b) -> a -> b
$ Maybe a -> Union (Maybe a)
forall (m :: * -> *) a.
(TryMerge m, Applicative m, Mergeable a) =>
a -> m a
mrgSingle Maybe a
forall a. Maybe a
Nothing
  fresh (Just aspec
aspec) = (Union (Maybe a) -> Union (Maybe a)
forall (m :: * -> *) a. (TryMerge m, Mergeable a) => m a -> m a
tryMerge (Union (Maybe a) -> Union (Maybe a))
-> (Union a -> Union (Maybe a)) -> Union a -> Union (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Maybe a) -> Union a -> Union (Maybe a)
forall a b. (a -> b) -> Union a -> Union b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Maybe a
forall a. a -> Maybe a
Just) (Union a -> Union (Maybe a)) -> m (Union a) -> m (Union (Maybe a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> aspec -> m (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => aspec -> m (Union a)
fresh aspec
aspec

instance
  (GenSymSimple aspec a) =>
  GenSymSimple (Maybe aspec) (Maybe a)
  where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => Maybe aspec -> m (Maybe a)
simpleFresh Maybe aspec
Nothing = Maybe a -> m (Maybe a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
  simpleFresh (Just aspec
aspec) = a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> m a -> m (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> aspec -> m a
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => aspec -> m a
simpleFresh aspec
aspec

instance
  {-# OVERLAPPABLE #-}
  (GenSym aspec a, Mergeable a) =>
  GenSym aspec (Maybe a)
  where
  fresh :: forall (m :: * -> *). MonadFresh m => aspec -> m (Union (Maybe a))
fresh aspec
aspec = do
    cond <- () -> m SymBool
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => () -> m SymBool
simpleFresh ()
    a :: Union a <- fresh aspec
    return $ mrgIf cond (mrgSingle Nothing) (Just <$> a)

-- List
instance
  (GenSym () a, Mergeable a) =>
  GenSym Integer [a]
  where
  fresh :: forall (m :: * -> *). MonadFresh m => Integer -> m (Union [a])
fresh Integer
v = do
    l <- Integer -> m [Union a]
forall (m :: * -> *). MonadFresh m => Integer -> m [Union a]
gl Integer
v
    let xs = [[Union a]] -> [[Union a]]
forall a. [a] -> [a]
reverse ([[Union a]] -> [[Union a]]) -> [[Union a]] -> [[Union a]]
forall a b. (a -> b) -> a -> b
$ (Union a -> [Union a] -> [Union a])
-> [Union a] -> [Union a] -> [[Union a]]
forall a b. (a -> b -> b) -> b -> [a] -> [b]
scanr (:) [] [Union a]
l
    chooseUnionFresh $ tryMerge . sequence <$> xs
    where
      gl :: (MonadFresh m) => Integer -> m [Union a]
      gl :: forall (m :: * -> *). MonadFresh m => Integer -> m [Union a]
gl Integer
v1
        | Integer
v1 Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
<= Integer
0 = [Union a] -> m [Union a]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return []
        | Bool
otherwise = do
            l <- () -> m (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => () -> m (Union a)
fresh ()
            r <- gl (v1 - 1)
            return $ l : r

-- | Specification for list generation.
--
-- >>> runFresh (fresh (ListSpec 0 2 ())) "c" :: Union [SymBool]
-- {If c@2 [] (If c@3 [c@1] [c@0,c@1])}
--
-- >>> runFresh (fresh (ListSpec 0 2 (SimpleListSpec 1 ()))) "c" :: Union [[SymBool]]
-- {If c@2 [] (If c@3 [[c@1]] [[c@0],[c@1]])}
data ListSpec spec = ListSpec
  { -- | The minimum length of the generated lists
    forall spec. ListSpec spec -> Int
genListMinLength :: Int,
    -- | The maximum length of the generated lists
    forall spec. ListSpec spec -> Int
genListMaxLength :: Int,
    -- | Each element in the lists will be generated with the sub-specification
    forall spec. ListSpec spec -> spec
genListSubSpec :: spec
  }
  deriving (Int -> ListSpec spec -> ShowS
[ListSpec spec] -> ShowS
ListSpec spec -> String
(Int -> ListSpec spec -> ShowS)
-> (ListSpec spec -> String)
-> ([ListSpec spec] -> ShowS)
-> Show (ListSpec spec)
forall spec. Show spec => Int -> ListSpec spec -> ShowS
forall spec. Show spec => [ListSpec spec] -> ShowS
forall spec. Show spec => ListSpec spec -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall spec. Show spec => Int -> ListSpec spec -> ShowS
showsPrec :: Int -> ListSpec spec -> ShowS
$cshow :: forall spec. Show spec => ListSpec spec -> String
show :: ListSpec spec -> String
$cshowList :: forall spec. Show spec => [ListSpec spec] -> ShowS
showList :: [ListSpec spec] -> ShowS
Show)

instance
  (GenSym spec a, Mergeable a) =>
  GenSym (ListSpec spec) [a]
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
ListSpec spec -> m (Union [a])
fresh (ListSpec Int
minLen Int
maxLen spec
subSpec) =
    if Int
minLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
|| Int
maxLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0 Bool -> Bool -> Bool
|| Int
minLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
maxLen
      then String -> m (Union [a])
forall a. HasCallStack => String -> a
error (String -> m (Union [a])) -> String -> m (Union [a])
forall a b. (a -> b) -> a -> b
$ String
"Bad lengths: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ (Int, Int) -> String
forall a. Show a => a -> String
show (Int
minLen, Int
maxLen)
      else do
        l <- Int -> m [Union a]
forall (m :: * -> *). MonadFresh m => Int -> m [Union a]
gl Int
maxLen
        let xs = Int -> [[Union a]] -> [[Union a]]
forall a. Int -> [a] -> [a]
drop Int
minLen ([[Union a]] -> [[Union a]]) -> [[Union a]] -> [[Union a]]
forall a b. (a -> b) -> a -> b
$ [[Union a]] -> [[Union a]]
forall a. [a] -> [a]
reverse ([[Union a]] -> [[Union a]]) -> [[Union a]] -> [[Union a]]
forall a b. (a -> b) -> a -> b
$ (Union a -> [Union a] -> [Union a])
-> [Union a] -> [Union a] -> [[Union a]]
forall a b. (a -> b -> b) -> b -> [a] -> [b]
scanr (:) [] [Union a]
l
        chooseUnionFresh $ tryMerge . sequence <$> xs
    where
      gl :: (MonadFresh m) => Int -> m [Union a]
      gl :: forall (m :: * -> *). MonadFresh m => Int -> m [Union a]
gl Int
currLen
        | Int
currLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = [Union a] -> m [Union a]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return []
        | Bool
otherwise = do
            l <- spec -> m (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => spec -> m (Union a)
fresh spec
subSpec
            r <- gl (currLen - 1)
            return $ l : r

instance
  (GenSym a a, Mergeable a) =>
  GenSym [a] [a]
  where
  fresh :: forall (m :: * -> *). MonadFresh m => [a] -> m (Union [a])
fresh [a]
l = do
    r :: [Union a] <- (a -> m (Union a)) -> [a] -> m [Union a]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse a -> m (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => a -> m (Union a)
fresh [a]
l
    return $ tryMerge $ sequence r

instance
  (GenSymSimple a a) =>
  GenSymSimple [a] [a]
  where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => [a] -> m [a]
simpleFresh = [a] -> m [a]
forall a (m :: * -> *).
(Generic a, GenSymSameShape (Rep a), MonadFresh m) =>
a -> m a
derivedSameShapeSimpleFresh

-- | Specification for list generation of a specific length.
--
-- >>> runFresh (simpleFresh (SimpleListSpec 2 ())) "c" :: [SymBool]
-- [c@0,c@1]
data SimpleListSpec spec = SimpleListSpec
  { -- | The length of the generated list
    forall spec. SimpleListSpec spec -> Int
genSimpleListLength :: Int,
    -- | Each element in the list will be generated with the sub-specification
    forall spec. SimpleListSpec spec -> spec
genSimpleListSubSpec :: spec
  }
  deriving (Int -> SimpleListSpec spec -> ShowS
[SimpleListSpec spec] -> ShowS
SimpleListSpec spec -> String
(Int -> SimpleListSpec spec -> ShowS)
-> (SimpleListSpec spec -> String)
-> ([SimpleListSpec spec] -> ShowS)
-> Show (SimpleListSpec spec)
forall spec. Show spec => Int -> SimpleListSpec spec -> ShowS
forall spec. Show spec => [SimpleListSpec spec] -> ShowS
forall spec. Show spec => SimpleListSpec spec -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall spec. Show spec => Int -> SimpleListSpec spec -> ShowS
showsPrec :: Int -> SimpleListSpec spec -> ShowS
$cshow :: forall spec. Show spec => SimpleListSpec spec -> String
show :: SimpleListSpec spec -> String
$cshowList :: forall spec. Show spec => [SimpleListSpec spec] -> ShowS
showList :: [SimpleListSpec spec] -> ShowS
Show)

instance
  (GenSym spec a, Mergeable a) =>
  GenSym (SimpleListSpec spec) [a]
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
SimpleListSpec spec -> m (Union [a])
fresh (SimpleListSpec Int
len spec
subSpec) =
    if Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0
      then String -> m (Union [a])
forall a. HasCallStack => String -> a
error (String -> m (Union [a])) -> String -> m (Union [a])
forall a b. (a -> b) -> a -> b
$ String
"Bad lengths: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
len
      else do
        Union [a] -> Union [a]
forall (m :: * -> *) a. (TryMerge m, Mergeable a) => m a -> m a
tryMerge (Union [a] -> Union [a])
-> ([Union a] -> Union [a]) -> [Union a] -> Union [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Union a] -> Union [a]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence ([Union a] -> Union [a]) -> m [Union a] -> m (Union [a])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int -> m [Union a]
forall (m :: * -> *). MonadFresh m => Int -> m [Union a]
gl Int
len
    where
      gl :: (MonadFresh m) => Int -> m [Union a]
      gl :: forall (m :: * -> *). MonadFresh m => Int -> m [Union a]
gl Int
currLen
        | Int
currLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = [Union a] -> m [Union a]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return []
        | Bool
otherwise = do
            l <- spec -> m (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => spec -> m (Union a)
fresh spec
subSpec
            r <- gl (currLen - 1)
            return $ l : r

instance
  (GenSymSimple spec a) =>
  GenSymSimple (SimpleListSpec spec) [a]
  where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => SimpleListSpec spec -> m [a]
simpleFresh (SimpleListSpec Int
len spec
subSpec) =
    if Int
len Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
0
      then String -> m [a]
forall a. HasCallStack => String -> a
error (String -> m [a]) -> String -> m [a]
forall a b. (a -> b) -> a -> b
$ String
"Bad lengths: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
len
      else do
        Int -> m [a]
forall (m :: * -> *). MonadFresh m => Int -> m [a]
gl Int
len
    where
      gl :: (MonadFresh m) => Int -> m [a]
      gl :: forall (m :: * -> *). MonadFresh m => Int -> m [a]
gl Int
currLen
        | Int
currLen Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0 = [a] -> m [a]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return []
        | Bool
otherwise = do
            l <- spec -> m a
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => spec -> m a
simpleFresh spec
subSpec
            r <- gl (currLen - 1)
            return $ l : r

-- ()
instance GenSym () ()

instance GenSymSimple () () where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => () -> m ()
simpleFresh = () -> m ()
forall a (m :: * -> *).
(Generic a, GenSymSimpleNoSpec (Rep a), MonadFresh m) =>
() -> m a
derivedNoSpecSimpleFresh

-- (,)
instance
  ( GenSym aspec a,
    Mergeable a,
    GenSym bspec b,
    Mergeable b
  ) =>
  GenSym (aspec, bspec) (a, b)
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
(aspec, bspec) -> m (Union (a, b))
fresh (aspec
aspec, bspec
bspec) = do
    a1 <- aspec -> m (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => aspec -> m (Union a)
fresh aspec
aspec
    b1 <- fresh bspec
    return $ do
      ax <- a1
      bx <- b1
      mrgSingle (ax, bx)

instance
  ( GenSymSimple aspec a,
    GenSymSimple bspec b
  ) =>
  GenSymSimple (aspec, bspec) (a, b)
  where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => (aspec, bspec) -> m (a, b)
simpleFresh (aspec
aspec, bspec
bspec) = do
    (,)
      (a -> b -> (a, b)) -> m a -> m (b -> (a, b))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> aspec -> m a
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => aspec -> m a
simpleFresh aspec
aspec
      m (b -> (a, b)) -> m b -> m (a, b)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> bspec -> m b
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => bspec -> m b
simpleFresh bspec
bspec

instance
  (GenSym () a, Mergeable a, GenSym () b, Mergeable b) =>
  GenSym () (a, b)
  where
  fresh :: forall (m :: * -> *). MonadFresh m => () -> m (Union (a, b))
fresh = () -> m (Union (a, b))
forall a (m :: * -> *).
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (Union a)
derivedNoSpecFresh

instance
  ( GenSymSimple () a,
    GenSymSimple () b
  ) =>
  GenSymSimple () (a, b)
  where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => () -> m (a, b)
simpleFresh = () -> m (a, b)
forall a (m :: * -> *).
(Generic a, GenSymSimpleNoSpec (Rep a), MonadFresh m) =>
() -> m a
derivedNoSpecSimpleFresh

-- (,,)
instance
  ( GenSym aspec a,
    Mergeable a,
    GenSym bspec b,
    Mergeable b,
    GenSym cspec c,
    Mergeable c
  ) =>
  GenSym (aspec, bspec, cspec) (a, b, c)
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
(aspec, bspec, cspec) -> m (Union (a, b, c))
fresh (aspec
aspec, bspec
bspec, cspec
cspec) = do
    a1 <- aspec -> m (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => aspec -> m (Union a)
fresh aspec
aspec
    b1 <- fresh bspec
    c1 <- fresh cspec
    return $ do
      ax <- a1
      bx <- b1
      cx <- c1
      mrgSingle (ax, bx, cx)

instance
  ( GenSymSimple aspec a,
    GenSymSimple bspec b,
    GenSymSimple cspec c
  ) =>
  GenSymSimple (aspec, bspec, cspec) (a, b, c)
  where
  simpleFresh :: forall (m :: * -> *).
MonadFresh m =>
(aspec, bspec, cspec) -> m (a, b, c)
simpleFresh (aspec
aspec, bspec
bspec, cspec
cspec) = do
    (,,)
      (a -> b -> c -> (a, b, c)) -> m a -> m (b -> c -> (a, b, c))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> aspec -> m a
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => aspec -> m a
simpleFresh aspec
aspec
      m (b -> c -> (a, b, c)) -> m b -> m (c -> (a, b, c))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> bspec -> m b
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => bspec -> m b
simpleFresh bspec
bspec
      m (c -> (a, b, c)) -> m c -> m (a, b, c)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> cspec -> m c
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => cspec -> m c
simpleFresh cspec
cspec

instance
  ( GenSym () a,
    Mergeable a,
    GenSym () b,
    Mergeable b,
    GenSym () c,
    Mergeable c
  ) =>
  GenSym () (a, b, c)
  where
  fresh :: forall (m :: * -> *). MonadFresh m => () -> m (Union (a, b, c))
fresh = () -> m (Union (a, b, c))
forall a (m :: * -> *).
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (Union a)
derivedNoSpecFresh

instance
  ( GenSymSimple () a,
    GenSymSimple () b,
    GenSymSimple () c
  ) =>
  GenSymSimple () (a, b, c)
  where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => () -> m (a, b, c)
simpleFresh = () -> m (a, b, c)
forall a (m :: * -> *).
(Generic a, GenSymSimpleNoSpec (Rep a), MonadFresh m) =>
() -> m a
derivedNoSpecSimpleFresh

-- (,,,)
instance
  ( GenSym aspec a,
    Mergeable a,
    GenSym bspec b,
    Mergeable b,
    GenSym cspec c,
    Mergeable c,
    GenSym dspec d,
    Mergeable d
  ) =>
  GenSym (aspec, bspec, cspec, dspec) (a, b, c, d)
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
(aspec, bspec, cspec, dspec) -> m (Union (a, b, c, d))
fresh (aspec
aspec, bspec
bspec, cspec
cspec, dspec
dspec) = do
    a1 <- aspec -> m (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => aspec -> m (Union a)
fresh aspec
aspec
    b1 <- fresh bspec
    c1 <- fresh cspec
    d1 <- fresh dspec
    return $ do
      ax <- a1
      bx <- b1
      cx <- c1
      dx <- d1
      mrgSingle (ax, bx, cx, dx)

instance
  ( GenSymSimple aspec a,
    GenSymSimple bspec b,
    GenSymSimple cspec c,
    GenSymSimple dspec d
  ) =>
  GenSymSimple (aspec, bspec, cspec, dspec) (a, b, c, d)
  where
  simpleFresh :: forall (m :: * -> *).
MonadFresh m =>
(aspec, bspec, cspec, dspec) -> m (a, b, c, d)
simpleFresh (aspec
aspec, bspec
bspec, cspec
cspec, dspec
dspec) = do
    (,,,)
      (a -> b -> c -> d -> (a, b, c, d))
-> m a -> m (b -> c -> d -> (a, b, c, d))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> aspec -> m a
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => aspec -> m a
simpleFresh aspec
aspec
      m (b -> c -> d -> (a, b, c, d))
-> m b -> m (c -> d -> (a, b, c, d))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> bspec -> m b
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => bspec -> m b
simpleFresh bspec
bspec
      m (c -> d -> (a, b, c, d)) -> m c -> m (d -> (a, b, c, d))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> cspec -> m c
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => cspec -> m c
simpleFresh cspec
cspec
      m (d -> (a, b, c, d)) -> m d -> m (a, b, c, d)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> dspec -> m d
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => dspec -> m d
simpleFresh dspec
dspec

instance
  ( GenSym () a,
    Mergeable a,
    GenSym () b,
    Mergeable b,
    GenSym () c,
    Mergeable c,
    GenSym () d,
    Mergeable d
  ) =>
  GenSym () (a, b, c, d)
  where
  fresh :: forall (m :: * -> *). MonadFresh m => () -> m (Union (a, b, c, d))
fresh = () -> m (Union (a, b, c, d))
forall a (m :: * -> *).
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (Union a)
derivedNoSpecFresh

instance
  ( GenSymSimple () a,
    GenSymSimple () b,
    GenSymSimple () c,
    GenSymSimple () d
  ) =>
  GenSymSimple () (a, b, c, d)
  where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => () -> m (a, b, c, d)
simpleFresh = () -> m (a, b, c, d)
forall a (m :: * -> *).
(Generic a, GenSymSimpleNoSpec (Rep a), MonadFresh m) =>
() -> m a
derivedNoSpecSimpleFresh

-- (,,,,)
instance
  ( GenSym aspec a,
    Mergeable a,
    GenSym bspec b,
    Mergeable b,
    GenSym cspec c,
    Mergeable c,
    GenSym dspec d,
    Mergeable d,
    GenSym espec e,
    Mergeable e
  ) =>
  GenSym (aspec, bspec, cspec, dspec, espec) (a, b, c, d, e)
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
(aspec, bspec, cspec, dspec, espec) -> m (Union (a, b, c, d, e))
fresh (aspec
aspec, bspec
bspec, cspec
cspec, dspec
dspec, espec
espec) = do
    a1 <- aspec -> m (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => aspec -> m (Union a)
fresh aspec
aspec
    b1 <- fresh bspec
    c1 <- fresh cspec
    d1 <- fresh dspec
    e1 <- fresh espec
    return $ do
      ax <- a1
      bx <- b1
      cx <- c1
      dx <- d1
      ex <- e1
      mrgSingle (ax, bx, cx, dx, ex)

instance
  ( GenSymSimple aspec a,
    GenSymSimple bspec b,
    GenSymSimple cspec c,
    GenSymSimple dspec d,
    GenSymSimple espec e
  ) =>
  GenSymSimple (aspec, bspec, cspec, dspec, espec) (a, b, c, d, e)
  where
  simpleFresh :: forall (m :: * -> *).
MonadFresh m =>
(aspec, bspec, cspec, dspec, espec) -> m (a, b, c, d, e)
simpleFresh (aspec
aspec, bspec
bspec, cspec
cspec, dspec
dspec, espec
espec) = do
    (,,,,)
      (a -> b -> c -> d -> e -> (a, b, c, d, e))
-> m a -> m (b -> c -> d -> e -> (a, b, c, d, e))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> aspec -> m a
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => aspec -> m a
simpleFresh aspec
aspec
      m (b -> c -> d -> e -> (a, b, c, d, e))
-> m b -> m (c -> d -> e -> (a, b, c, d, e))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> bspec -> m b
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => bspec -> m b
simpleFresh bspec
bspec
      m (c -> d -> e -> (a, b, c, d, e))
-> m c -> m (d -> e -> (a, b, c, d, e))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> cspec -> m c
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => cspec -> m c
simpleFresh cspec
cspec
      m (d -> e -> (a, b, c, d, e)) -> m d -> m (e -> (a, b, c, d, e))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> dspec -> m d
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => dspec -> m d
simpleFresh dspec
dspec
      m (e -> (a, b, c, d, e)) -> m e -> m (a, b, c, d, e)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> espec -> m e
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => espec -> m e
simpleFresh espec
espec

instance
  ( GenSym () a,
    Mergeable a,
    GenSym () b,
    Mergeable b,
    GenSym () c,
    Mergeable c,
    GenSym () d,
    Mergeable d,
    GenSym () e,
    Mergeable e
  ) =>
  GenSym () (a, b, c, d, e)
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
() -> m (Union (a, b, c, d, e))
fresh = () -> m (Union (a, b, c, d, e))
forall a (m :: * -> *).
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (Union a)
derivedNoSpecFresh

instance
  ( GenSymSimple () a,
    GenSymSimple () b,
    GenSymSimple () c,
    GenSymSimple () d,
    GenSymSimple () e
  ) =>
  GenSymSimple () (a, b, c, d, e)
  where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => () -> m (a, b, c, d, e)
simpleFresh = () -> m (a, b, c, d, e)
forall a (m :: * -> *).
(Generic a, GenSymSimpleNoSpec (Rep a), MonadFresh m) =>
() -> m a
derivedNoSpecSimpleFresh

-- (,,,,,)
instance
  ( GenSym aspec a,
    Mergeable a,
    GenSym bspec b,
    Mergeable b,
    GenSym cspec c,
    Mergeable c,
    GenSym dspec d,
    Mergeable d,
    GenSym espec e,
    Mergeable e,
    GenSym fspec f,
    Mergeable f
  ) =>
  GenSym (aspec, bspec, cspec, dspec, espec, fspec) (a, b, c, d, e, f)
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
(aspec, bspec, cspec, dspec, espec, fspec)
-> m (Union (a, b, c, d, e, f))
fresh (aspec
aspec, bspec
bspec, cspec
cspec, dspec
dspec, espec
espec, fspec
fspec) = do
    a1 <- aspec -> m (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => aspec -> m (Union a)
fresh aspec
aspec
    b1 <- fresh bspec
    c1 <- fresh cspec
    d1 <- fresh dspec
    e1 <- fresh espec
    f1 <- fresh fspec
    return $ do
      ax <- a1
      bx <- b1
      cx <- c1
      dx <- d1
      ex <- e1
      fx <- f1
      mrgSingle (ax, bx, cx, dx, ex, fx)

instance
  ( GenSymSimple aspec a,
    GenSymSimple bspec b,
    GenSymSimple cspec c,
    GenSymSimple dspec d,
    GenSymSimple espec e,
    GenSymSimple fspec f
  ) =>
  GenSymSimple (aspec, bspec, cspec, dspec, espec, fspec) (a, b, c, d, e, f)
  where
  simpleFresh :: forall (m :: * -> *).
MonadFresh m =>
(aspec, bspec, cspec, dspec, espec, fspec) -> m (a, b, c, d, e, f)
simpleFresh (aspec
aspec, bspec
bspec, cspec
cspec, dspec
dspec, espec
espec, fspec
fspec) = do
    (,,,,,)
      (a -> b -> c -> d -> e -> f -> (a, b, c, d, e, f))
-> m a -> m (b -> c -> d -> e -> f -> (a, b, c, d, e, f))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> aspec -> m a
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => aspec -> m a
simpleFresh aspec
aspec
      m (b -> c -> d -> e -> f -> (a, b, c, d, e, f))
-> m b -> m (c -> d -> e -> f -> (a, b, c, d, e, f))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> bspec -> m b
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => bspec -> m b
simpleFresh bspec
bspec
      m (c -> d -> e -> f -> (a, b, c, d, e, f))
-> m c -> m (d -> e -> f -> (a, b, c, d, e, f))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> cspec -> m c
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => cspec -> m c
simpleFresh cspec
cspec
      m (d -> e -> f -> (a, b, c, d, e, f))
-> m d -> m (e -> f -> (a, b, c, d, e, f))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> dspec -> m d
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => dspec -> m d
simpleFresh dspec
dspec
      m (e -> f -> (a, b, c, d, e, f))
-> m e -> m (f -> (a, b, c, d, e, f))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> espec -> m e
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => espec -> m e
simpleFresh espec
espec
      m (f -> (a, b, c, d, e, f)) -> m f -> m (a, b, c, d, e, f)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> fspec -> m f
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => fspec -> m f
simpleFresh fspec
fspec

instance
  ( GenSym () a,
    Mergeable a,
    GenSym () b,
    Mergeable b,
    GenSym () c,
    Mergeable c,
    GenSym () d,
    Mergeable d,
    GenSym () e,
    Mergeable e,
    GenSym () f,
    Mergeable f
  ) =>
  GenSym () (a, b, c, d, e, f)
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
() -> m (Union (a, b, c, d, e, f))
fresh = () -> m (Union (a, b, c, d, e, f))
forall a (m :: * -> *).
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (Union a)
derivedNoSpecFresh

instance
  ( GenSymSimple () a,
    GenSymSimple () b,
    GenSymSimple () c,
    GenSymSimple () d,
    GenSymSimple () e,
    GenSymSimple () f
  ) =>
  GenSymSimple () (a, b, c, d, e, f)
  where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => () -> m (a, b, c, d, e, f)
simpleFresh = () -> m (a, b, c, d, e, f)
forall a (m :: * -> *).
(Generic a, GenSymSimpleNoSpec (Rep a), MonadFresh m) =>
() -> m a
derivedNoSpecSimpleFresh

-- (,,,,,,)
instance
  ( GenSym aspec a,
    Mergeable a,
    GenSym bspec b,
    Mergeable b,
    GenSym cspec c,
    Mergeable c,
    GenSym dspec d,
    Mergeable d,
    GenSym espec e,
    Mergeable e,
    GenSym fspec f,
    Mergeable f,
    GenSym gspec g,
    Mergeable g
  ) =>
  GenSym (aspec, bspec, cspec, dspec, espec, fspec, gspec) (a, b, c, d, e, f, g)
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
(aspec, bspec, cspec, dspec, espec, fspec, gspec)
-> m (Union (a, b, c, d, e, f, g))
fresh (aspec
aspec, bspec
bspec, cspec
cspec, dspec
dspec, espec
espec, fspec
fspec, gspec
gspec) = do
    a1 <- aspec -> m (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => aspec -> m (Union a)
fresh aspec
aspec
    b1 <- fresh bspec
    c1 <- fresh cspec
    d1 <- fresh dspec
    e1 <- fresh espec
    f1 <- fresh fspec
    g1 <- fresh gspec
    return $ do
      ax <- a1
      bx <- b1
      cx <- c1
      dx <- d1
      ex <- e1
      fx <- f1
      gx <- g1
      mrgSingle (ax, bx, cx, dx, ex, fx, gx)

instance
  ( GenSymSimple aspec a,
    GenSymSimple bspec b,
    GenSymSimple cspec c,
    GenSymSimple dspec d,
    GenSymSimple espec e,
    GenSymSimple fspec f,
    GenSymSimple gspec g
  ) =>
  GenSymSimple (aspec, bspec, cspec, dspec, espec, fspec, gspec) (a, b, c, d, e, f, g)
  where
  simpleFresh :: forall (m :: * -> *).
MonadFresh m =>
(aspec, bspec, cspec, dspec, espec, fspec, gspec)
-> m (a, b, c, d, e, f, g)
simpleFresh (aspec
aspec, bspec
bspec, cspec
cspec, dspec
dspec, espec
espec, fspec
fspec, gspec
gspec) = do
    (,,,,,,)
      (a -> b -> c -> d -> e -> f -> g -> (a, b, c, d, e, f, g))
-> m a -> m (b -> c -> d -> e -> f -> g -> (a, b, c, d, e, f, g))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> aspec -> m a
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => aspec -> m a
simpleFresh aspec
aspec
      m (b -> c -> d -> e -> f -> g -> (a, b, c, d, e, f, g))
-> m b -> m (c -> d -> e -> f -> g -> (a, b, c, d, e, f, g))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> bspec -> m b
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => bspec -> m b
simpleFresh bspec
bspec
      m (c -> d -> e -> f -> g -> (a, b, c, d, e, f, g))
-> m c -> m (d -> e -> f -> g -> (a, b, c, d, e, f, g))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> cspec -> m c
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => cspec -> m c
simpleFresh cspec
cspec
      m (d -> e -> f -> g -> (a, b, c, d, e, f, g))
-> m d -> m (e -> f -> g -> (a, b, c, d, e, f, g))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> dspec -> m d
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => dspec -> m d
simpleFresh dspec
dspec
      m (e -> f -> g -> (a, b, c, d, e, f, g))
-> m e -> m (f -> g -> (a, b, c, d, e, f, g))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> espec -> m e
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => espec -> m e
simpleFresh espec
espec
      m (f -> g -> (a, b, c, d, e, f, g))
-> m f -> m (g -> (a, b, c, d, e, f, g))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> fspec -> m f
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => fspec -> m f
simpleFresh fspec
fspec
      m (g -> (a, b, c, d, e, f, g)) -> m g -> m (a, b, c, d, e, f, g)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> gspec -> m g
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => gspec -> m g
simpleFresh gspec
gspec

instance
  ( GenSym () a,
    Mergeable a,
    GenSym () b,
    Mergeable b,
    GenSym () c,
    Mergeable c,
    GenSym () d,
    Mergeable d,
    GenSym () e,
    Mergeable e,
    GenSym () f,
    Mergeable f,
    GenSym () g,
    Mergeable g
  ) =>
  GenSym () (a, b, c, d, e, f, g)
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
() -> m (Union (a, b, c, d, e, f, g))
fresh = () -> m (Union (a, b, c, d, e, f, g))
forall a (m :: * -> *).
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (Union a)
derivedNoSpecFresh

instance
  ( GenSymSimple () a,
    GenSymSimple () b,
    GenSymSimple () c,
    GenSymSimple () d,
    GenSymSimple () e,
    GenSymSimple () f,
    GenSymSimple () g
  ) =>
  GenSymSimple () (a, b, c, d, e, f, g)
  where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => () -> m (a, b, c, d, e, f, g)
simpleFresh = () -> m (a, b, c, d, e, f, g)
forall a (m :: * -> *).
(Generic a, GenSymSimpleNoSpec (Rep a), MonadFresh m) =>
() -> m a
derivedNoSpecSimpleFresh

-- (,,,,,,,)
instance
  ( GenSym aspec a,
    Mergeable a,
    GenSym bspec b,
    Mergeable b,
    GenSym cspec c,
    Mergeable c,
    GenSym dspec d,
    Mergeable d,
    GenSym espec e,
    Mergeable e,
    GenSym fspec f,
    Mergeable f,
    GenSym gspec g,
    Mergeable g,
    GenSym hspec h,
    Mergeable h
  ) =>
  GenSym (aspec, bspec, cspec, dspec, espec, fspec, gspec, hspec) (a, b, c, d, e, f, g, h)
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
(aspec, bspec, cspec, dspec, espec, fspec, gspec, hspec)
-> m (Union (a, b, c, d, e, f, g, h))
fresh (aspec
aspec, bspec
bspec, cspec
cspec, dspec
dspec, espec
espec, fspec
fspec, gspec
gspec, hspec
hspec) = do
    a1 <- aspec -> m (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => aspec -> m (Union a)
fresh aspec
aspec
    b1 <- fresh bspec
    c1 <- fresh cspec
    d1 <- fresh dspec
    e1 <- fresh espec
    f1 <- fresh fspec
    g1 <- fresh gspec
    h1 <- fresh hspec
    return $ do
      ax <- a1
      bx <- b1
      cx <- c1
      dx <- d1
      ex <- e1
      fx <- f1
      gx <- g1
      hx <- h1
      mrgSingle (ax, bx, cx, dx, ex, fx, gx, hx)

instance
  ( GenSymSimple aspec a,
    GenSymSimple bspec b,
    GenSymSimple cspec c,
    GenSymSimple dspec d,
    GenSymSimple espec e,
    GenSymSimple fspec f,
    GenSymSimple gspec g,
    GenSymSimple hspec h
  ) =>
  GenSymSimple (aspec, bspec, cspec, dspec, espec, fspec, gspec, hspec) (a, b, c, d, e, f, g, h)
  where
  simpleFresh :: forall (m :: * -> *).
MonadFresh m =>
(aspec, bspec, cspec, dspec, espec, fspec, gspec, hspec)
-> m (a, b, c, d, e, f, g, h)
simpleFresh (aspec
aspec, bspec
bspec, cspec
cspec, dspec
dspec, espec
espec, fspec
fspec, gspec
gspec, hspec
hspec) = do
    (,,,,,,,)
      (a -> b -> c -> d -> e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
-> m a
-> m (b -> c -> d -> e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> aspec -> m a
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => aspec -> m a
simpleFresh aspec
aspec
      m (b -> c -> d -> e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
-> m b
-> m (c -> d -> e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> bspec -> m b
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => bspec -> m b
simpleFresh bspec
bspec
      m (c -> d -> e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
-> m c -> m (d -> e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> cspec -> m c
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => cspec -> m c
simpleFresh cspec
cspec
      m (d -> e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
-> m d -> m (e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> dspec -> m d
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => dspec -> m d
simpleFresh dspec
dspec
      m (e -> f -> g -> h -> (a, b, c, d, e, f, g, h))
-> m e -> m (f -> g -> h -> (a, b, c, d, e, f, g, h))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> espec -> m e
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => espec -> m e
simpleFresh espec
espec
      m (f -> g -> h -> (a, b, c, d, e, f, g, h))
-> m f -> m (g -> h -> (a, b, c, d, e, f, g, h))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> fspec -> m f
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => fspec -> m f
simpleFresh fspec
fspec
      m (g -> h -> (a, b, c, d, e, f, g, h))
-> m g -> m (h -> (a, b, c, d, e, f, g, h))
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> gspec -> m g
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => gspec -> m g
simpleFresh gspec
gspec
      m (h -> (a, b, c, d, e, f, g, h))
-> m h -> m (a, b, c, d, e, f, g, h)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> hspec -> m h
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => hspec -> m h
simpleFresh hspec
hspec

instance
  ( GenSym () a,
    Mergeable a,
    GenSym () b,
    Mergeable b,
    GenSym () c,
    Mergeable c,
    GenSym () d,
    Mergeable d,
    GenSym () e,
    Mergeable e,
    GenSym () f,
    Mergeable f,
    GenSym () g,
    Mergeable g,
    GenSym () h,
    Mergeable h
  ) =>
  GenSym () (a, b, c, d, e, f, g, h)
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
() -> m (Union (a, b, c, d, e, f, g, h))
fresh = () -> m (Union (a, b, c, d, e, f, g, h))
forall a (m :: * -> *).
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (Union a)
derivedNoSpecFresh

instance
  ( GenSymSimple () a,
    GenSymSimple () b,
    GenSymSimple () c,
    GenSymSimple () d,
    GenSymSimple () e,
    GenSymSimple () f,
    GenSymSimple () g,
    GenSymSimple () h
  ) =>
  GenSymSimple () (a, b, c, d, e, f, g, h)
  where
  simpleFresh :: forall (m :: * -> *).
MonadFresh m =>
() -> m (a, b, c, d, e, f, g, h)
simpleFresh = () -> m (a, b, c, d, e, f, g, h)
forall a (m :: * -> *).
(Generic a, GenSymSimpleNoSpec (Rep a), MonadFresh m) =>
() -> m a
derivedNoSpecSimpleFresh

-- MaybeT
instance
  {-# OVERLAPPABLE #-}
  ( GenSym spec (m (Maybe a)),
    Mergeable1 m,
    Mergeable a
  ) =>
  GenSym spec (MaybeT m a)
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
spec -> m (Union (MaybeT m a))
fresh spec
v = do
    x <- spec -> m (Union (m (Maybe a)))
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *).
MonadFresh m =>
spec -> m (Union (m (Maybe a)))
fresh spec
v
    return $ tryMerge . fmap MaybeT $ x

instance
  {-# OVERLAPPABLE #-}
  (GenSymSimple spec (m (Maybe a))) =>
  GenSymSimple spec (MaybeT m a)
  where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => spec -> m (MaybeT m a)
simpleFresh spec
v = m (Maybe a) -> MaybeT m a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m (Maybe a) -> MaybeT m a) -> m (m (Maybe a)) -> m (MaybeT m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> spec -> m (m (Maybe a))
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => spec -> m (m (Maybe a))
simpleFresh spec
v

instance
  {-# OVERLAPPING #-}
  (GenSymSimple (m (Maybe a)) (m (Maybe a))) =>
  GenSymSimple (MaybeT m a) (MaybeT m a)
  where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => MaybeT m a -> m (MaybeT m a)
simpleFresh (MaybeT m (Maybe a)
v) = m (Maybe a) -> MaybeT m a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m (Maybe a) -> MaybeT m a) -> m (m (Maybe a)) -> m (MaybeT m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Maybe a) -> m (m (Maybe a))
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *).
MonadFresh m =>
m (Maybe a) -> m (m (Maybe a))
simpleFresh m (Maybe a)
v

instance
  {-# OVERLAPPING #-}
  ( GenSymSimple (m (Maybe a)) (m (Maybe a)),
    Mergeable1 m,
    Mergeable a
  ) =>
  GenSym (MaybeT m a) (MaybeT m a)

-- ExceptT
instance
  {-# OVERLAPPABLE #-}
  ( GenSym spec (m (Either a b)),
    Mergeable1 m,
    Mergeable a,
    Mergeable b
  ) =>
  GenSym spec (ExceptT a m b)
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
spec -> m (Union (ExceptT a m b))
fresh spec
v = do
    x <- spec -> m (Union (m (Either a b)))
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *).
MonadFresh m =>
spec -> m (Union (m (Either a b)))
fresh spec
v
    return $ tryMerge . fmap ExceptT $ x

instance
  {-# OVERLAPPABLE #-}
  (GenSymSimple spec (m (Either a b))) =>
  GenSymSimple spec (ExceptT a m b)
  where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => spec -> m (ExceptT a m b)
simpleFresh spec
v = m (Either a b) -> ExceptT a m b
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT (m (Either a b) -> ExceptT a m b)
-> m (m (Either a b)) -> m (ExceptT a m b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> spec -> m (m (Either a b))
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => spec -> m (m (Either a b))
simpleFresh spec
v

instance
  {-# OVERLAPPING #-}
  (GenSymSimple (m (Either e a)) (m (Either e a))) =>
  GenSymSimple (ExceptT e m a) (ExceptT e m a)
  where
  simpleFresh :: forall (m :: * -> *).
MonadFresh m =>
ExceptT e m a -> m (ExceptT e m a)
simpleFresh (ExceptT m (Either e a)
v) = m (Either e a) -> ExceptT e m a
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT (m (Either e a) -> ExceptT e m a)
-> m (m (Either e a)) -> m (ExceptT e m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Either e a) -> m (m (Either e a))
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *).
MonadFresh m =>
m (Either e a) -> m (m (Either e a))
simpleFresh m (Either e a)
v

instance
  {-# OVERLAPPING #-}
  ( GenSymSimple (m (Either e a)) (m (Either e a)),
    Mergeable1 m,
    Mergeable e,
    Mergeable a
  ) =>
  GenSym (ExceptT e m a) (ExceptT e m a)

#define GENSYM_SIMPLE(symtype) \
instance GenSym symtype symtype
#define GENSYM_SIMPLE_SIMPLE(symtype) \
instance GenSymSimple symtype symtype where \
  simpleFresh _ = simpleFresh ()
#define GENSYM_UNIT_SIMPLE(symtype) \
instance GenSym () symtype where \
  fresh _ = mrgSingle <$> simpleFresh ()
#define GENSYM_UNIT_SIMPLE_SIMPLE(symtype) \
instance GenSymSimple () symtype where \
  simpleFresh _ = do; \
    ident <- getIdentifier; \
    FreshIndex index <- nextFreshIndex; \
    return $ isym ident index

#define GENSYM_BV(symtype) \
instance (KnownNat n, 1 <= n) => GenSym (symtype n) (symtype n)
#define GENSYM_SIMPLE_BV(symtype) \
instance (KnownNat n, 1 <= n) => GenSymSimple (symtype n) (symtype n) where \
  simpleFresh _ = simpleFresh ()
#define GENSYM_UNIT_BV(symtype) \
instance (KnownNat n, 1 <= n) => GenSym () (symtype n) where \
  fresh _ = mrgSingle <$> simpleFresh ()
#define GENSYM_UNIT_SIMPLE_BV(symtype) \
instance (KnownNat n, 1 <= n) => GenSymSimple () (symtype n) where \
  simpleFresh _ = do; \
    ident <- getIdentifier; \
    FreshIndex index <- nextFreshIndex; \
    return $ isym ident index

#define GENSYM_FUN(cop, op, consop) \
instance GenSym (op sa sb) (op sa sb) where \
  fresh consop{} = fresh ()
#define GENSYM_SIMPLE_FUN(cop, op, consop) \
instance GenSymSimple (op sa sb) (op sa sb) where \
  simpleFresh consop{} = simpleFresh ()
#define GENSYM_UNIT_FUN(cop, op) \
instance \
  ( SupportedPrim (cop ca cb), \
    SupportedNonFuncPrim ca, \
    LinkedRep ca sa, \
    LinkedRep cb sb \
  ) => \
  GenSym () (op sa sb) where \
  fresh _ = mrgSingle <$> simpleFresh ()
#define GENSYM_UNIT_SIMPLE_FUN(cop, op) \
instance \
  ( SupportedPrim (cop ca cb), \
    SupportedNonFuncPrim ca, \
    LinkedRep ca sa, \
    LinkedRep cb sb \
  ) => \
  GenSymSimple () (op sa sb) where \
  simpleFresh _ = do; \
    ident <- getIdentifier; \
    FreshIndex index <- nextFreshIndex; \
    return $ isym ident index

#if 1
GENSYM_SIMPLE(SymBool)
GENSYM_SIMPLE_SIMPLE(SymBool)
GENSYM_UNIT_SIMPLE(SymBool)
GENSYM_UNIT_SIMPLE_SIMPLE(SymBool)
GENSYM_SIMPLE(SymInteger)
GENSYM_SIMPLE_SIMPLE(SymInteger)
GENSYM_UNIT_SIMPLE(SymInteger)
GENSYM_UNIT_SIMPLE_SIMPLE(SymInteger)
GENSYM_SIMPLE(SymFPRoundingMode)
GENSYM_SIMPLE_SIMPLE(SymFPRoundingMode)
GENSYM_UNIT_SIMPLE(SymFPRoundingMode)
GENSYM_UNIT_SIMPLE_SIMPLE(SymFPRoundingMode)
GENSYM_SIMPLE(SymAlgReal)
GENSYM_SIMPLE_SIMPLE(SymAlgReal)
GENSYM_UNIT_SIMPLE(SymAlgReal)
GENSYM_UNIT_SIMPLE_SIMPLE(SymAlgReal)

GENSYM_BV(SymIntN)
GENSYM_SIMPLE_BV(SymIntN)
GENSYM_UNIT_BV(SymIntN)
GENSYM_UNIT_SIMPLE_BV(SymIntN)
GENSYM_BV(SymWordN)
GENSYM_SIMPLE_BV(SymWordN)
GENSYM_UNIT_BV(SymWordN)
GENSYM_UNIT_SIMPLE_BV(SymWordN)

GENSYM_FUN((=->), (=~>), SymTabularFun)
GENSYM_SIMPLE_FUN((=->), (=~>), SymTabularFun)
GENSYM_UNIT_FUN((=->), (=~>))
GENSYM_UNIT_SIMPLE_FUN((=->), (=~>))
GENSYM_FUN((-->), (-~>), SymGeneralFun)
GENSYM_SIMPLE_FUN((-->), (-~>), SymGeneralFun)
GENSYM_UNIT_FUN((-->), (-~>))
GENSYM_UNIT_SIMPLE_FUN((-->), (-~>))
#endif

instance (ValidFP eb sb) => GenSym (SymFP eb sb) (SymFP eb sb)

instance (ValidFP eb sb) => GenSymSimple (SymFP eb sb) (SymFP eb sb) where
  simpleFresh :: forall (m :: * -> *).
MonadFresh m =>
SymFP eb sb -> m (SymFP eb sb)
simpleFresh SymFP eb sb
_ = () -> m (SymFP eb sb)
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => () -> m (SymFP eb sb)
simpleFresh ()

instance (ValidFP eb sb) => GenSym () (SymFP eb sb) where
  fresh :: forall (m :: * -> *). MonadFresh m => () -> m (Union (SymFP eb sb))
fresh ()
_ = SymFP eb sb -> Union (SymFP eb sb)
forall (m :: * -> *) a.
(TryMerge m, Applicative m, Mergeable a) =>
a -> m a
mrgSingle (SymFP eb sb -> Union (SymFP eb sb))
-> m (SymFP eb sb) -> m (Union (SymFP eb sb))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> () -> m (SymFP eb sb)
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => () -> m (SymFP eb sb)
simpleFresh ()

instance (ValidFP eb sb) => GenSymSimple () (SymFP eb sb) where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => () -> m (SymFP eb sb)
simpleFresh ()
_ = do
    ident <- m Identifier
forall (m :: * -> *). MonadFresh m => m Identifier
getIdentifier
    FreshIndex index <- nextFreshIndex
    return $ isym ident index

instance (GenSym spec a, Mergeable a) => GenSym spec (Union a)

instance (GenSym spec a) => GenSymSimple spec (Union a) where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => spec -> m (Union a)
simpleFresh spec
spec = do
    res <- spec -> m (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => spec -> m (Union a)
fresh spec
spec
    if not (isMerged res) then error "Not merged" else return res

instance
  (GenSym a a, Mergeable a) =>
  GenSym (Union a) a
  where
  fresh :: forall (m :: * -> *). MonadFresh m => Union a -> m (Union a)
fresh Union a
spec = UnionBase a -> m (Union a)
forall {spec} {a} {m :: * -> *}.
(GenSym spec a, MonadFresh m) =>
UnionBase spec -> m (Union a)
go (Union a -> UnionBase a
forall a. Union a -> UnionBase a
unionBase (Union a -> UnionBase a) -> Union a -> UnionBase a
forall a b. (a -> b) -> a -> b
$ Union a -> Union a
forall (m :: * -> *) a. (TryMerge m, Mergeable a) => m a -> m a
tryMerge Union a
spec)
    where
      go :: UnionBase spec -> m (Union a)
go (UnionSingle spec
x) = spec -> m (Union a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (Union a)
forall (m :: * -> *). MonadFresh m => spec -> m (Union a)
fresh spec
x
      go (UnionIf spec
_ Bool
_ SymBool
_ UnionBase spec
t UnionBase spec
f) = SymBool -> Union a -> Union a -> Union a
forall (u :: * -> *) a.
(SymBranching u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf (SymBool -> Union a -> Union a -> Union a)
-> m SymBool -> m (Union a -> Union a -> Union a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> () -> m SymBool
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
forall (m :: * -> *). MonadFresh m => () -> m SymBool
simpleFresh () m (Union a -> Union a -> Union a)
-> m (Union a) -> m (Union a -> Union a)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> UnionBase spec -> m (Union a)
go UnionBase spec
t m (Union a -> Union a) -> m (Union a) -> m (Union a)
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> UnionBase spec -> m (Union a)
go UnionBase spec
f