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

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

    -- * Monad for fresh symbolic value generation
    MonadFresh (..),
    FreshT,
    Fresh,
    runFreshT,
    runFresh,

    -- * 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.DeepSeq
import Control.Monad.Except
import Control.Monad.Identity
import Control.Monad.Signatures
import Control.Monad.Trans.Maybe
import Data.Bifunctor
import qualified Data.ByteString as B
import Data.Hashable
import Data.Int
import Data.String
import Data.Typeable
import Data.Word
import Generics.Deriving hiding (index)
import Grisette.Core.Control.Monad.Union
import {-# SOURCE #-} Grisette.Core.Control.Monad.UnionM
import Grisette.Core.Data.Class.Bool
import Grisette.Core.Data.Class.Mergeable
import Grisette.Core.Data.Class.SimpleMergeable
import Grisette.Core.Data.Class.Solvable
import Grisette.IR.SymPrim.Data.Prim.InternedTerm.Term
import {-# SOURCE #-} Grisette.IR.SymPrim.Data.SymPrim
import Language.Haskell.TH.Syntax hiding (lift)

-- $setup
-- >>> import Grisette.Core
-- >>> import Grisette.IR.SymPrim
-- >>> :set -XOverloadedStrings
-- >>> :set -XTypeApplications

-- | 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
showList :: [FreshIndex] -> ShowS
$cshowList :: [FreshIndex] -> ShowS
show :: FreshIndex -> String
$cshow :: FreshIndex -> String
showsPrec :: Int -> FreshIndex -> ShowS
$cshowsPrec :: Int -> 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
/= :: FreshIndex -> FreshIndex -> Bool
$c/= :: FreshIndex -> FreshIndex -> Bool
== :: FreshIndex -> FreshIndex -> Bool
$c== :: 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
min :: FreshIndex -> FreshIndex -> FreshIndex
$cmin :: FreshIndex -> FreshIndex -> FreshIndex
max :: FreshIndex -> FreshIndex -> FreshIndex
$cmax :: FreshIndex -> FreshIndex -> FreshIndex
>= :: FreshIndex -> FreshIndex -> Bool
$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
compare :: FreshIndex -> FreshIndex -> Ordering
$ccompare :: FreshIndex -> FreshIndex -> Ordering
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
fromInteger :: Integer -> FreshIndex
$cfromInteger :: Integer -> FreshIndex
signum :: FreshIndex -> FreshIndex
$csignum :: FreshIndex -> FreshIndex
abs :: FreshIndex -> FreshIndex
$cabs :: FreshIndex -> FreshIndex
negate :: FreshIndex -> FreshIndex
$cnegate :: FreshIndex -> FreshIndex
* :: FreshIndex -> FreshIndex -> FreshIndex
$c* :: FreshIndex -> FreshIndex -> FreshIndex
- :: FreshIndex -> FreshIndex -> FreshIndex
$c- :: FreshIndex -> FreshIndex -> FreshIndex
+ :: FreshIndex -> FreshIndex -> FreshIndex
$c+ :: FreshIndex -> FreshIndex -> 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

-- | Identifier type used for 'GenSym'
--
-- The constructor is hidden intentionally.
-- You can construct an identifier by:
--
--   * a raw name
--
--     The following two expressions will refer to the same identifier (the
--     solver won't distinguish them and would assign the same value to them).
--     The user may need to use unique names to avoid unintentional identifier
--     collision.
--
--     >>> name "a"
--     a
--
--     >>> "a" :: FreshIdent -- available when OverloadedStrings is enabled
--     a
--
--   * bundle the calling file location with the name to ensure global uniqueness
--
--     Identifiers created at different locations will not be the
--     same. The identifiers created at the same location will be the same.
--
--     >>> $$(nameWithLoc "a") -- a sample result could be "a:<interactive>:18:4-18"
--     a:<interactive>:...
--
--   * bundle the calling file location with some user provided information
--
--     Identifiers created with different name or different additional
--     information will not be the same.
--
--     >>> nameWithInfo "a" (1 :: Int)
--     a:1
data FreshIdent where
  FreshIdent :: String -> FreshIdent
  FreshIdentWithInfo :: (Typeable a, Ord a, Lift a, NFData a, Show a, Hashable a) => String -> a -> FreshIdent

instance Show FreshIdent where
  show :: FreshIdent -> String
show (FreshIdent String
i) = String
i
  show (FreshIdentWithInfo String
s a
i) = String
s String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
":" String -> ShowS
forall a. [a] -> [a] -> [a]
++ a -> String
forall a. Show a => a -> String
show a
i

instance IsString FreshIdent where
  fromString :: String -> FreshIdent
fromString = String -> FreshIdent
name

instance Eq FreshIdent where
  FreshIdent String
l == :: FreshIdent -> FreshIdent -> Bool
== FreshIdent String
r = String
l String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
r
  FreshIdentWithInfo String
l (a
linfo :: linfo) == FreshIdentWithInfo String
r (a
rinfo :: rinfo) = case forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
forall a b. (Typeable a, Typeable b) => Maybe (a :~: b)
eqT @linfo @rinfo of
    Just a :~: a
Refl -> String
l String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
r Bool -> Bool -> Bool
&& a
linfo a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
a
rinfo
    Maybe (a :~: a)
_ -> Bool
False
  FreshIdent
_ == FreshIdent
_ = Bool
False

instance Ord FreshIdent where
  FreshIdent String
l <= :: FreshIdent -> FreshIdent -> Bool
<= FreshIdent String
r = String
l String -> String -> Bool
forall a. Ord a => a -> a -> Bool
<= String
r
  FreshIdent String
_ <= FreshIdent
_ = Bool
True
  FreshIdent
_ <= FreshIdent String
_ = Bool
False
  FreshIdentWithInfo String
l (a
linfo :: linfo) <= FreshIdentWithInfo String
r (a
rinfo :: rinfo) =
    String
l String -> String -> Bool
forall a. Ord a => a -> a -> Bool
< String
r
      Bool -> Bool -> Bool
|| ( String
l String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
r
             Bool -> Bool -> Bool
&& ( case forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
forall a b. (Typeable a, Typeable b) => Maybe (a :~: b)
eqT @linfo @rinfo of
                    Just a :~: a
Refl -> a
linfo a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
a
rinfo
                    Maybe (a :~: a)
_ -> Proxy a -> TypeRep
forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (forall {t}. Proxy t
forall {k} (t :: k). Proxy t
Proxy @linfo) TypeRep -> TypeRep -> Bool
forall a. Ord a => a -> a -> Bool
<= Proxy a -> TypeRep
forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (forall {t}. Proxy t
forall {k} (t :: k). Proxy t
Proxy @rinfo)
                )
         )

instance Hashable FreshIdent where
  hashWithSalt :: Int -> FreshIdent -> Int
hashWithSalt Int
s (FreshIdent String
n) = Int
s Int -> String -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` String
n
  hashWithSalt Int
s (FreshIdentWithInfo String
n a
i) = Int
s Int -> String -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` String
n Int -> a -> Int
forall a. Hashable a => Int -> a -> Int
`hashWithSalt` a
i

instance Lift FreshIdent where
  liftTyped :: forall (m :: * -> *). Quote m => FreshIdent -> Code m FreshIdent
liftTyped (FreshIdent String
n) = [||FreshIdent n||]
  liftTyped (FreshIdentWithInfo String
n a
i) = [||FreshIdentWithInfo n i||]

instance NFData FreshIdent where
  rnf :: FreshIdent -> ()
rnf (FreshIdent String
n) = String -> ()
forall a. NFData a => a -> ()
rnf String
n
  rnf (FreshIdentWithInfo String
n a
i) = String -> ()
forall a. NFData a => a -> ()
rnf String
n () -> () -> ()
`seq` a -> ()
forall a. NFData a => a -> ()
rnf a
i

-- | Simple name identifier.
-- The same identifier refers to the same symbolic variable in the whole program.
--
-- The user may need to use unique names to avoid unintentional identifier
-- collision.
name :: String -> FreshIdent
name :: String -> FreshIdent
name = String -> FreshIdent
FreshIdent

-- | Identifier with extra information.
-- The same name with the same information
-- refers to the same symbolic variable in the whole program.
--
-- The user may need to use unique names or additional information to avoid
-- unintentional identifier collision.
nameWithInfo :: forall a. (Typeable a, Ord a, Lift a, NFData a, Show a, Hashable a) => String -> a -> FreshIdent
nameWithInfo :: forall a.
(Typeable a, Ord a, Lift a, NFData a, Show a, Hashable a) =>
String -> a -> FreshIdent
nameWithInfo = String -> a -> FreshIdent
forall a.
(Typeable a, Ord a, Lift a, NFData a, Show a, Hashable a) =>
String -> a -> FreshIdent
FreshIdentWithInfo

-- | Monad class for fresh symbolic value generation.
--
-- The monad should be a reader monad for the 'FreshIdent' and a state monad for
-- the 'FreshIndex'.
class Monad m => MonadFresh m where
  -- | Increase the index by one and return the new index.
  nextFreshIndex :: m FreshIndex

  -- | Get the identifier.
  getFreshIdent :: m FreshIdent

-- | A symbolic generation monad transformer.
-- It is a reader monad transformer for identifiers 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 -> FreshIdent -> FreshIndex -> m (a, FreshIndex)
runFreshT' :: FreshIdent -> FreshIndex -> m (a, FreshIndex)}

instance
  (Mergeable a, Mergeable1 m) =>
  Mergeable (FreshT m a)
  where
  rootStrategy :: MergingStrategy (FreshT m a)
rootStrategy =
    MergingStrategy (FreshIdent -> FreshIndex -> m (a, FreshIndex))
-> ((FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (FreshT m a -> FreshIdent -> 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 (FreshIdent -> FreshIndex -> m (a, FreshIndex))
forall (u :: * -> *) a.
Mergeable1 u =>
MergingStrategy a -> MergingStrategy (u a)
liftRootStrategy (MergingStrategy (m (a, FreshIndex))
-> MergingStrategy (FreshIndex -> m (a, FreshIndex))
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)) (FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT FreshT m a -> FreshIdent -> FreshIndex -> m (a, FreshIndex)
forall (m :: * -> *) a.
FreshT m a -> FreshIdent -> FreshIndex -> m (a, FreshIndex)
runFreshT'

instance (Mergeable1 m) => Mergeable1 (FreshT m) where
  liftRootStrategy :: forall a. MergingStrategy a -> MergingStrategy (FreshT m a)
liftRootStrategy MergingStrategy a
m =
    MergingStrategy (FreshIdent -> FreshIndex -> m (a, FreshIndex))
-> ((FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (FreshT m a -> FreshIdent -> 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 (FreshIdent -> FreshIndex -> m (a, FreshIndex))
forall (u :: * -> *) a.
Mergeable1 u =>
MergingStrategy a -> MergingStrategy (u a)
liftRootStrategy (MergingStrategy (m (a, FreshIndex))
-> MergingStrategy (FreshIndex -> m (a, FreshIndex))
forall (u :: * -> *) a.
Mergeable1 u =>
MergingStrategy a -> MergingStrategy (u a)
liftRootStrategy (MergingStrategy (a, FreshIndex)
-> MergingStrategy (m (a, FreshIndex))
forall (u :: * -> *) a.
Mergeable1 u =>
MergingStrategy a -> MergingStrategy (u a)
liftRootStrategy (MergingStrategy a
-> MergingStrategy FreshIndex -> MergingStrategy (a, FreshIndex)
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))))
      (FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT
      FreshT m a -> FreshIdent -> FreshIndex -> m (a, FreshIndex)
forall (m :: * -> *) a.
FreshT m a -> FreshIdent -> FreshIndex -> m (a, FreshIndex)
runFreshT'

instance
  (UnionLike 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.
(UnionLike u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf

instance
  (UnionLike 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 (u :: * -> *) a.
UnionLike 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
  (UnionLike m) =>
  UnionLike (FreshT m)
  where
  mergeWithStrategy :: forall a. MergingStrategy a -> FreshT m a -> FreshT m a
mergeWithStrategy MergingStrategy a
s (FreshT FreshIdent -> FreshIndex -> m (a, FreshIndex)
f) =
    (FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall a b. (a -> b) -> a -> b
$ \FreshIdent
ident FreshIndex
index -> MergingStrategy (a, FreshIndex)
-> m (a, FreshIndex) -> m (a, FreshIndex)
forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> u a -> u a
mergeWithStrategy (MergingStrategy a
-> MergingStrategy FreshIndex -> MergingStrategy (a, FreshIndex)
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
$ FreshIdent -> FreshIndex -> m (a, FreshIndex)
f FreshIdent
ident FreshIndex
index
  mrgIfWithStrategy :: forall a.
MergingStrategy a
-> SymBool -> FreshT m a -> FreshT m a -> FreshT m a
mrgIfWithStrategy MergingStrategy a
s SymBool
cond (FreshT FreshIdent -> FreshIndex -> m (a, FreshIndex)
t) (FreshT FreshIdent -> FreshIndex -> m (a, FreshIndex)
f) =
    (FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall a b. (a -> b) -> a -> b
$ \FreshIdent
ident FreshIndex
index -> MergingStrategy (a, FreshIndex)
-> SymBool
-> m (a, FreshIndex)
-> m (a, FreshIndex)
-> m (a, FreshIndex)
forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (MergingStrategy a
-> MergingStrategy FreshIndex -> MergingStrategy (a, FreshIndex)
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 (FreshIdent -> FreshIndex -> m (a, FreshIndex)
t FreshIdent
ident FreshIndex
index) (FreshIdent -> FreshIndex -> m (a, FreshIndex)
f FreshIdent
ident FreshIndex
index)
  single :: forall a. a -> FreshT m a
single a
x = (FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall a b. (a -> b) -> a -> b
$ \FreshIdent
_ FreshIndex
i -> (a, FreshIndex) -> m (a, FreshIndex)
forall (u :: * -> *) a. UnionLike u => a -> u a
single (a
x, FreshIndex
i)
  unionIf :: forall a. SymBool -> FreshT m a -> FreshT m a -> FreshT m a
unionIf SymBool
cond (FreshT FreshIdent -> FreshIndex -> m (a, FreshIndex)
t) (FreshT FreshIdent -> FreshIndex -> m (a, FreshIndex)
f) =
    (FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall a b. (a -> b) -> a -> b
$ \FreshIdent
ident FreshIndex
index -> SymBool
-> m (a, FreshIndex) -> m (a, FreshIndex) -> m (a, FreshIndex)
forall (u :: * -> *) a. UnionLike u => SymBool -> u a -> u a -> u a
unionIf SymBool
cond (FreshIdent -> FreshIndex -> m (a, FreshIndex)
t FreshIdent
ident FreshIndex
index) (FreshIdent -> FreshIndex -> m (a, FreshIndex)
f FreshIdent
ident FreshIndex
index)

-- | Run the symbolic generation with the given identifier and 0 as the initial index.
runFreshT :: (Monad m) => FreshT m a -> FreshIdent -> m a
runFreshT :: forall (m :: * -> *) a. Monad m => FreshT m a -> FreshIdent -> m a
runFreshT FreshT m a
m FreshIdent
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 -> FreshIdent -> FreshIndex -> m (a, FreshIndex)
forall (m :: * -> *) a.
FreshT m a -> FreshIdent -> FreshIndex -> m (a, FreshIndex)
runFreshT' FreshT m a
m FreshIdent
ident (Int -> FreshIndex
FreshIndex Int
0)

instance (Functor f) => Functor (FreshT f) where
  fmap :: forall a b. (a -> b) -> FreshT f a -> FreshT f b
fmap a -> b
f (FreshT FreshIdent -> FreshIndex -> f (a, FreshIndex)
s) = (FreshIdent -> FreshIndex -> f (b, FreshIndex)) -> FreshT f b
forall (m :: * -> *) a.
(FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((FreshIdent -> FreshIndex -> f (b, FreshIndex)) -> FreshT f b)
-> (FreshIdent -> FreshIndex -> f (b, FreshIndex)) -> FreshT f b
forall a b. (a -> b) -> a -> b
$ \FreshIdent
ident FreshIndex
idx -> (a -> b) -> (a, FreshIndex) -> (b, FreshIndex)
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
<$> FreshIdent -> FreshIndex -> f (a, FreshIndex)
s FreshIdent
ident FreshIndex
idx

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

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

instance MonadTrans FreshT where
  lift :: forall (m :: * -> *) a. Monad m => m a -> FreshT m a
lift m a
x = (FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall a b. (a -> b) -> a -> b
$ \FreshIdent
_ 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 FreshIdent -> FreshIndex -> m (a, FreshIndex)
m) e -> FreshT m a
h =
  (FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall (m :: * -> *) a.
(FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a)
-> (FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
forall a b. (a -> b) -> a -> b
$ \FreshIdent
ident FreshIndex
index -> FreshIdent -> FreshIndex -> m (a, FreshIndex)
m FreshIdent
ident FreshIndex
index Catch e m (a, FreshIndex)
`catchE` \e
e -> FreshT m a -> FreshIdent -> FreshIndex -> m (a, FreshIndex)
forall (m :: * -> *) a.
FreshT m a -> FreshIdent -> FreshIndex -> m (a, FreshIndex)
runFreshT' (e -> FreshT m a
h e
e) FreshIdent
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 (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 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 e (m :: * -> *) a.
MonadError e m =>
m a -> (e -> m a) -> m a
catchError

-- | '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 -> FreshIdent -> a
runFresh :: forall a. Fresh a -> FreshIdent -> a
runFresh Fresh a
m FreshIdent
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 -> FreshIdent -> Identity a
forall (m :: * -> *) a. Monad m => FreshT m a -> FreshIdent -> m a
runFreshT Fresh a
m FreshIdent
ident

instance Monad m => MonadFresh (FreshT m) where
  nextFreshIndex :: FreshT m FreshIndex
nextFreshIndex = (FreshIdent -> FreshIndex -> m (FreshIndex, FreshIndex))
-> FreshT m FreshIndex
forall (m :: * -> *) a.
(FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((FreshIdent -> FreshIndex -> m (FreshIndex, FreshIndex))
 -> FreshT m FreshIndex)
-> (FreshIdent -> FreshIndex -> m (FreshIndex, FreshIndex))
-> FreshT m FreshIndex
forall a b. (a -> b) -> a -> b
$ \FreshIdent
_ FreshIndex
idx -> (FreshIndex, FreshIndex) -> m (FreshIndex, FreshIndex)
forall (m :: * -> *) a. Monad m => a -> m a
return (FreshIndex
idx, FreshIndex
idx FreshIndex -> FreshIndex -> FreshIndex
forall a. Num a => a -> a -> a
+ FreshIndex
1)
  getFreshIdent :: FreshT m FreshIdent
getFreshIdent = (FreshIdent -> FreshIndex -> m (FreshIdent, FreshIndex))
-> FreshT m FreshIdent
forall (m :: * -> *) a.
(FreshIdent -> FreshIndex -> m (a, FreshIndex)) -> FreshT m a
FreshT ((FreshIdent -> FreshIndex -> m (FreshIdent, FreshIndex))
 -> FreshT m FreshIdent)
-> (FreshIdent -> FreshIndex -> m (FreshIdent, FreshIndex))
-> FreshT m FreshIdent
forall a b. (a -> b) -> a -> b
$ ((FreshIdent, FreshIndex) -> m (FreshIdent, FreshIndex))
-> FreshIdent -> FreshIndex -> m (FreshIdent, FreshIndex)
forall a b c. ((a, b) -> c) -> a -> b -> c
curry (FreshIdent, FreshIndex) -> m (FreshIdent, FreshIndex)
forall (m :: * -> *) a. Monad m => a -> m a
return

-- | 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 '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" :: UnionM 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" :: UnionM 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" :: UnionM (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" :: UnionM [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" :: (UnionM SymBool, UnionM SymBool)
  -- ({a@0},{a@1})
  fresh ::
    (MonadFresh m) =>
    spec ->
    m (UnionM a)
  default fresh ::
    (GenSymSimple spec a) =>
    ( MonadFresh m
    ) =>
    spec ->
    m (UnionM a)
  fresh spec
spec = a -> UnionM a
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (a -> UnionM a) -> m a -> m (UnionM 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
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" :: UnionM [SymBool]
-- {If a@2 [a@1] [a@0,a@1]}
genSym :: (GenSym spec a) => spec -> FreshIdent -> UnionM a
genSym :: forall spec a. GenSym spec a => spec -> FreshIdent -> UnionM a
genSym = Fresh (UnionM a) -> FreshIdent -> UnionM a
forall a. Fresh a -> FreshIdent -> a
runFresh (Fresh (UnionM a) -> FreshIdent -> UnionM a)
-> (spec -> Fresh (UnionM a)) -> spec -> FreshIdent -> UnionM a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. spec -> Fresh (UnionM a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM 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 '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 -> FreshIdent -> a
genSymSimple :: forall spec a. GenSymSimple spec a => spec -> FreshIdent -> a
genSymSimple = Fresh a -> FreshIdent -> a
forall a. Fresh a -> FreshIdent -> a
runFresh (Fresh a -> FreshIdent -> a)
-> (spec -> Fresh a) -> spec -> FreshIdent -> 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
simpleFresh

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

instance GenSymNoSpec U1 where
  freshNoSpec :: forall (m :: * -> *) c. MonadFresh m => m (UnionM (U1 c))
freshNoSpec = UnionM (U1 c) -> m (UnionM (U1 c))
forall (m :: * -> *) a. Monad m => a -> m a
return (UnionM (U1 c) -> m (UnionM (U1 c)))
-> UnionM (U1 c) -> m (UnionM (U1 c))
forall a b. (a -> b) -> a -> b
$ U1 c -> UnionM (U1 c)
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u 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 (UnionM (K1 i c c))
freshNoSpec = (c -> K1 i c c) -> UnionM c -> UnionM (K1 i c c)
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 (UnionM c -> UnionM (K1 i c c))
-> m (UnionM c) -> m (UnionM (K1 i c c))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> () -> m (UnionM c)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh ()

instance (GenSymNoSpec a) => GenSymNoSpec (M1 i c a) where
  freshNoSpec :: forall (m :: * -> *) c. MonadFresh m => m (UnionM (M1 i c a c))
freshNoSpec = (a c -> M1 i c a c) -> UnionM (a c) -> UnionM (M1 i c a c)
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 (UnionM (a c) -> UnionM (M1 i c a c))
-> m (UnionM (a c)) -> m (UnionM (M1 i c a c))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (UnionM (a c))
forall (a :: * -> *) (m :: * -> *) c.
(GenSymNoSpec a, MonadFresh m) =>
m (UnionM (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 u c.
    ( MonadFresh m
    ) =>
    m (UnionM ((a :+: b) c))
  freshNoSpec :: forall (m :: * -> *) u c. MonadFresh m => m (UnionM ((:+:) a b c))
freshNoSpec = do
    SymBool
cond :: bool <- () -> m SymBool
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
simpleFresh ()
    UnionM (a c)
l :: UnionM (a c) <- m (UnionM (a c))
forall (a :: * -> *) (m :: * -> *) c.
(GenSymNoSpec a, MonadFresh m) =>
m (UnionM (a c))
freshNoSpec
    UnionM (b c)
r :: UnionM (b c) <- m (UnionM (b c))
forall (a :: * -> *) (m :: * -> *) c.
(GenSymNoSpec a, MonadFresh m) =>
m (UnionM (a c))
freshNoSpec
    UnionM ((:+:) a b c) -> m (UnionM ((:+:) a b c))
forall (m :: * -> *) a. Monad m => a -> m a
return (UnionM ((:+:) a b c) -> m (UnionM ((:+:) a b c)))
-> UnionM ((:+:) a b c) -> m (UnionM ((:+:) a b c))
forall a b. (a -> b) -> a -> b
$ SymBool
-> UnionM ((:+:) a b c)
-> UnionM ((:+:) a b c)
-> UnionM ((:+:) a b c)
forall (u :: * -> *) a.
(UnionLike u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf SymBool
cond ((a c -> (:+:) a b c) -> UnionM (a c) -> UnionM ((:+:) a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a c -> (:+:) a b c
forall k (f :: k -> *) (g :: k -> *) (p :: k). f p -> (:+:) f g p
L1 UnionM (a c)
l) ((b c -> (:+:) a b c) -> UnionM (b c) -> UnionM ((:+:) a b c)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b c -> (:+:) a b c
forall k (f :: k -> *) (g :: k -> *) (p :: k). g p -> (:+:) f g p
R1 UnionM (b c)
r)

instance
  (GenSymNoSpec a, GenSymNoSpec b) =>
  GenSymNoSpec (a :*: b)
  where
  freshNoSpec ::
    forall m u c.
    ( MonadFresh m
    ) =>
    m (UnionM ((a :*: b) c))
  freshNoSpec :: forall (m :: * -> *) u c. MonadFresh m => m (UnionM ((:*:) a b c))
freshNoSpec = do
    UnionM (a c)
l :: UnionM (a c) <- m (UnionM (a c))
forall (a :: * -> *) (m :: * -> *) c.
(GenSymNoSpec a, MonadFresh m) =>
m (UnionM (a c))
freshNoSpec
    UnionM (b c)
r :: UnionM (b c) <- m (UnionM (b c))
forall (a :: * -> *) (m :: * -> *) c.
(GenSymNoSpec a, MonadFresh m) =>
m (UnionM (a c))
freshNoSpec
    UnionM ((:*:) a b c) -> m (UnionM ((:*:) a b c))
forall (m :: * -> *) a. Monad m => a -> m a
return (UnionM ((:*:) a b c) -> m (UnionM ((:*:) a b c)))
-> UnionM ((:*:) a b c) -> m (UnionM ((:*:) a b c))
forall a b. (a -> b) -> a -> b
$ do
      a c
l1 <- UnionM (a c)
l
      b c
r1 <- UnionM (b c)
r
      (:*:) a b c -> UnionM ((:*:) a b c)
forall (m :: * -> *) a. Monad m => a -> m a
return ((:*:) a b c -> UnionM ((:*:) a b c))
-> (:*:) a b c -> UnionM ((:*:) a b c)
forall a b. (a -> b) -> a -> b
$ a c
l1 a c -> b c -> (:*:) a b c
forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
:*: b c
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 bool a m u.
  ( Generic a,
    GenSymNoSpec (Rep a),
    Mergeable a,
    MonadFresh m
  ) =>
  () ->
  m (UnionM a)
derivedNoSpecFresh :: forall bool a (m :: * -> *) u.
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (UnionM a)
derivedNoSpecFresh ()
_ = UnionM a -> UnionM a
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => u a -> u a
merge (UnionM a -> UnionM a)
-> (UnionM (Rep a Any) -> UnionM a)
-> UnionM (Rep a Any)
-> UnionM a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Rep a Any -> a) -> UnionM (Rep a Any) -> UnionM a
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
to (UnionM (Rep a Any) -> UnionM a)
-> m (UnionM (Rep a Any)) -> m (UnionM a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (UnionM (Rep a Any))
forall (a :: * -> *) (m :: * -> *) c.
(GenSymNoSpec a, MonadFresh m) =>
m (UnionM (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 (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
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)
simpleFreshNoSpec

instance
  (GenSymSimpleNoSpec a, GenSymSimpleNoSpec b) =>
  GenSymSimpleNoSpec (a :*: b)
  where
  simpleFreshNoSpec :: forall (m :: * -> *) c. MonadFresh m => m ((:*:) a b c)
simpleFreshNoSpec = do
    a c
l :: a c <- m (a c)
forall (a :: * -> *) (m :: * -> *) c.
(GenSymSimpleNoSpec a, MonadFresh m) =>
m (a c)
simpleFreshNoSpec
    b c
r :: b c <- m (b c)
forall (a :: * -> *) (m :: * -> *) c.
(GenSymSimpleNoSpec a, MonadFresh m) =>
m (a c)
simpleFreshNoSpec
    (:*:) a b c -> m ((:*:) a b c)
forall (m :: * -> *) a. Monad m => a -> m a
return ((:*:) a b c -> m ((:*:) a b c)) -> (:*:) a b c -> m ((:*:) a b c)
forall a b. (a -> b) -> a -> b
$ a c
l a c -> b c -> (:*:) a b c
forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
:*: b c
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
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)
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 (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
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)
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)
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)
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
    a c
l :: a c <- a c -> m (a c)
forall (a :: * -> *) (m :: * -> *) c.
(GenSymSameShape a, MonadFresh m) =>
a c -> m (a c)
genSymSameShapeFresh a c
a
    b c
r :: b c <- b c -> m (b c)
forall (a :: * -> *) (m :: * -> *) c.
(GenSymSameShape a, MonadFresh m) =>
a c -> m (a c)
genSymSameShapeFresh b c
b
    (:*:) a b c -> m ((:*:) a b c)
forall (m :: * -> *) a. Monad m => a -> m a
return ((:*:) a b c -> m ((:*:) a b c)) -> (:*:) a b c -> m ((:*:) a b c)
forall a b. (a -> b) -> a -> b
$ a c
l a c -> b c -> (:*:) a b c
forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
:*: b c
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
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)
genSymSameShapeFresh (a -> Rep a Any
forall a x. Generic a => a -> Rep a x
from a
a)

-- | 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" :: UnionM Integer
-- {If a@0 1 (If a@1 2 3)}
chooseFresh ::
  forall bool a m u.
  ( Mergeable a,
    MonadFresh m
  ) =>
  [a] ->
  m (UnionM a)
chooseFresh :: forall bool a (m :: * -> *) u.
(Mergeable a, MonadFresh m) =>
[a] -> m (UnionM a)
chooseFresh [a
x] = UnionM a -> m (UnionM a)
forall (m :: * -> *) a. Monad m => a -> m a
return (UnionM a -> m (UnionM a)) -> UnionM a -> m (UnionM a)
forall a b. (a -> b) -> a -> b
$ a -> UnionM a
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle a
x
chooseFresh (a
r : [a]
rs) = do
  SymBool
b <- () -> m SymBool
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
simpleFresh ()
  UnionM a
res <- [a] -> m (UnionM a)
forall bool a (m :: * -> *) u.
(Mergeable a, MonadFresh m) =>
[a] -> m (UnionM a)
chooseFresh [a]
rs
  UnionM a -> m (UnionM a)
forall (m :: * -> *) a. Monad m => a -> m a
return (UnionM a -> m (UnionM a)) -> UnionM a -> m (UnionM a)
forall a b. (a -> b) -> a -> b
$ SymBool -> UnionM a -> UnionM a -> UnionM a
forall (u :: * -> *) a.
(UnionLike u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf SymBool
b (a -> UnionM a
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle a
r) UnionM a
res
chooseFresh [] = String -> m (UnionM a)
forall a. HasCallStack => String -> a
error String
"chooseFresh expects at least one value"

-- | 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 bool a u.
  ( Mergeable a
  ) =>
  [a] ->
  FreshIdent ->
  UnionM a
choose :: forall bool a u. Mergeable a => [a] -> FreshIdent -> UnionM a
choose = Fresh (UnionM a) -> FreshIdent -> UnionM a
forall a. Fresh a -> FreshIdent -> a
runFresh (Fresh (UnionM a) -> FreshIdent -> UnionM a)
-> ([a] -> Fresh (UnionM a)) -> [a] -> FreshIdent -> UnionM a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Fresh (UnionM a)
forall bool a (m :: * -> *) u.
(Mergeable a, MonadFresh m) =>
[a] -> m (UnionM 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
x] = a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x
chooseSimpleFresh (a
r : [a]
rs) = do
  SymBool
b :: bool <- () -> m SymBool
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
simpleFresh ()
  a
res <- [a] -> m a
forall a (m :: * -> *).
(SimpleMergeable a, MonadFresh m) =>
[a] -> m a
chooseSimpleFresh [a]
rs
  a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> m a) -> a -> m a
forall a b. (a -> b) -> a -> b
$ SymBool -> a -> a -> a
forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
b a
r a
res
chooseSimpleFresh [] = String -> m a
forall a. HasCallStack => String -> a
error String
"chooseSimpleFresh expects at least one value"

-- | 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] ->
  FreshIdent ->
  a
chooseSimple :: forall a. SimpleMergeable a => [a] -> FreshIdent -> a
chooseSimple = Fresh a -> FreshIdent -> a
forall a. Fresh a -> FreshIdent -> a
runFresh (Fresh a -> FreshIdent -> a)
-> ([a] -> Fresh a) -> [a] -> FreshIdent -> 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" :: UnionM Integer
-- >>> let b = runFresh (chooseFresh [2, 3]) "b" :: UnionM Integer
-- >>> runFresh (chooseUnionFresh [a, b]) "c" :: UnionM Integer
-- {If (&& c@0 a@0) 1 (If (|| c@0 b@0) 2 3)}
chooseUnionFresh ::
  forall bool a m u.
  ( Mergeable a,
    MonadFresh m
  ) =>
  [UnionM a] ->
  m (UnionM a)
chooseUnionFresh :: forall bool a (m :: * -> *) u.
(Mergeable a, MonadFresh m) =>
[UnionM a] -> m (UnionM a)
chooseUnionFresh [UnionM a
x] = UnionM a -> m (UnionM a)
forall (m :: * -> *) a. Monad m => a -> m a
return UnionM a
x
chooseUnionFresh (UnionM a
r : [UnionM a]
rs) = do
  SymBool
b <- () -> m SymBool
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
simpleFresh ()
  UnionM a
res <- [UnionM a] -> m (UnionM a)
forall bool a (m :: * -> *) u.
(Mergeable a, MonadFresh m) =>
[UnionM a] -> m (UnionM a)
chooseUnionFresh [UnionM a]
rs
  UnionM a -> m (UnionM a)
forall (m :: * -> *) a. Monad m => a -> m a
return (UnionM a -> m (UnionM a)) -> UnionM a -> m (UnionM a)
forall a b. (a -> b) -> a -> b
$ SymBool -> UnionM a -> UnionM a -> UnionM a
forall (u :: * -> *) a.
(UnionLike u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf SymBool
b UnionM a
r UnionM a
res
chooseUnionFresh [] = String -> m (UnionM a)
forall a. HasCallStack => String -> a
error String
"chooseUnionFresh expects at least one value"

-- | 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 u.
  ( Mergeable a
  ) =>
  [UnionM a] ->
  FreshIdent ->
  UnionM a
chooseUnion :: forall a u. Mergeable a => [UnionM a] -> FreshIdent -> UnionM a
chooseUnion = Fresh (UnionM a) -> FreshIdent -> UnionM a
forall a. Fresh a -> FreshIdent -> a
runFresh (Fresh (UnionM a) -> FreshIdent -> UnionM a)
-> ([UnionM a] -> Fresh (UnionM a))
-> [UnionM a]
-> FreshIdent
-> UnionM a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [UnionM a] -> Fresh (UnionM a)
forall bool a (m :: * -> *) u.
(Mergeable a, MonadFresh m) =>
[UnionM a] -> m (UnionM 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

#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(B.ByteString)

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(B.ByteString)
#endif

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

-- Enums

-- | Specification for enum values with upper bound (exclusive). The result would chosen from [0 .. upperbound].
--
-- >>> runFresh (fresh (EnumGenUpperBound @Integer 4)) "c" :: UnionM 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 (UnionM v)
fresh (EnumGenUpperBound v
u) = [v] -> m (UnionM v)
forall bool a (m :: * -> *) u.
(Mergeable a, MonadFresh m) =>
[a] -> m (UnionM 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" :: UnionM 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 (UnionM v)
fresh (EnumGenBound v
l v
u) = [v] -> m (UnionM v)
forall bool a (m :: * -> *) u.
(Mergeable a, MonadFresh m) =>
[a] -> m (UnionM 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
  ( GenSymSimple a a,
    Mergeable a,
    GenSymSimple b b,
    Mergeable b
  ) =>
  GenSym (Either a b) (Either a b)

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

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

-- Maybe
instance
  (GenSymSimple a a, Mergeable a) =>
  GenSym (Maybe a) (Maybe a)

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

instance (GenSym () a, Mergeable a) => GenSym () (Maybe a) where
  fresh :: forall (m :: * -> *). MonadFresh m => () -> m (UnionM (Maybe a))
fresh = () -> m (UnionM (Maybe a))
forall bool a (m :: * -> *) u.
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (UnionM a)
derivedNoSpecFresh

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

-- | Specification for list generation.
--
-- >>> runFresh (fresh (ListSpec 0 2 ())) "c" :: UnionM [SymBool]
-- {If c@2 [] (If c@3 [c@1] [c@0,c@1])}
--
-- >>> runFresh (fresh (ListSpec 0 2 (SimpleListSpec 1 ()))) "c" :: UnionM [[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
showList :: [ListSpec spec] -> ShowS
$cshowList :: forall spec. Show spec => [ListSpec spec] -> ShowS
show :: ListSpec spec -> String
$cshow :: forall spec. Show spec => ListSpec spec -> String
showsPrec :: Int -> ListSpec spec -> ShowS
$cshowsPrec :: forall spec. Show spec => Int -> ListSpec spec -> ShowS
Show)

instance
  (GenSymSimple spec a, Mergeable a) =>
  GenSym (ListSpec spec) [a]
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
ListSpec spec -> m (UnionM [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 (UnionM [a])
forall a. HasCallStack => String -> a
error (String -> m (UnionM [a])) -> String -> m (UnionM [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
        [a]
l <- Int -> m [a]
forall (m :: * -> *). MonadFresh m => Int -> m [a]
gl Int
maxLen
        let xs :: [[a]]
xs = Int -> [[a]] -> [[a]]
forall a. Int -> [a] -> [a]
drop Int
minLen ([[a]] -> [[a]]) -> [[a]] -> [[a]]
forall a b. (a -> b) -> a -> b
$ [[a]] -> [[a]]
forall a. [a] -> [a]
reverse ([[a]] -> [[a]]) -> [[a]] -> [[a]]
forall a b. (a -> b) -> a -> b
$ (a -> [a] -> [a]) -> [a] -> [a] -> [[a]]
forall a b. (a -> b -> b) -> b -> [a] -> [b]
scanr (:) [] [a]
l
        [[a]] -> m (UnionM [a])
forall bool a (m :: * -> *) u.
(Mergeable a, MonadFresh m) =>
[a] -> m (UnionM a)
chooseFresh [[a]]
xs
    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 (m :: * -> *) a. Monad m => a -> m a
return []
        | Bool
otherwise = do
            a
l <- spec -> m a
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
simpleFresh spec
subSpec
            [a]
r <- Int -> m [a]
forall (m :: * -> *). MonadFresh m => Int -> m [a]
gl (Int
currLen Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
            [a] -> m [a]
forall (m :: * -> *) a. Monad m => a -> m a
return ([a] -> m [a]) -> [a] -> m [a]
forall a b. (a -> b) -> a -> b
$ a
l a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
r

instance
  (GenSymSimple a a, Mergeable a) =>
  GenSym [a] [a]

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
showList :: [SimpleListSpec spec] -> ShowS
$cshowList :: forall spec. Show spec => [SimpleListSpec spec] -> ShowS
show :: SimpleListSpec spec -> String
$cshow :: forall spec. Show spec => SimpleListSpec spec -> String
showsPrec :: Int -> SimpleListSpec spec -> ShowS
$cshowsPrec :: forall spec. Show spec => Int -> SimpleListSpec spec -> ShowS
Show)

instance
  (GenSymSimple spec a, Mergeable a) =>
  GenSym (SimpleListSpec spec) [a]
  where
  fresh :: forall (m :: * -> *).
MonadFresh m =>
SimpleListSpec spec -> m (UnionM [a])
fresh = ([a] -> UnionM [a]) -> m [a] -> m (UnionM [a])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [a] -> UnionM [a]
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (m [a] -> m (UnionM [a]))
-> (SimpleListSpec spec -> m [a])
-> SimpleListSpec spec
-> m (UnionM [a])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SimpleListSpec spec -> m [a]
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
simpleFresh

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 (m :: * -> *) a. Monad m => a -> m a
return []
        | Bool
otherwise = do
            a
l <- spec -> m a
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
simpleFresh spec
subSpec
            [a]
r <- Int -> m [a]
forall (m :: * -> *). MonadFresh m => Int -> m [a]
gl (Int
currLen Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
            [a] -> m [a]
forall (m :: * -> *) a. Monad m => a -> m a
return ([a] -> m [a]) -> [a] -> m [a]
forall a b. (a -> b) -> a -> b
$ a
l a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
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 (UnionM (a, b))
fresh (aspec
aspec, bspec
bspec) = do
    UnionM a
a1 <- aspec -> m (UnionM a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh aspec
aspec
    UnionM b
b1 <- bspec -> m (UnionM b)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh bspec
bspec
    UnionM (a, b) -> m (UnionM (a, b))
forall (m :: * -> *) a. Monad m => a -> m a
return (UnionM (a, b) -> m (UnionM (a, b)))
-> UnionM (a, b) -> m (UnionM (a, b))
forall a b. (a -> b) -> a -> b
$ do
      a
ax <- UnionM a
a1
      b
bx <- UnionM b
b1
      (a, b) -> UnionM (a, b)
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (a
ax, b
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
simpleFresh aspec
aspec
      m (b -> (a, b)) -> m b -> m (a, 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
simpleFresh bspec
bspec

instance
  (GenSym () a, Mergeable a, GenSym () b, Mergeable b) =>
  GenSym () (a, b)
  where
  fresh :: forall (m :: * -> *). MonadFresh m => () -> m (UnionM (a, b))
fresh = () -> m (UnionM (a, b))
forall bool a (m :: * -> *) u.
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (UnionM 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 (UnionM (a, b, c))
fresh (aspec
aspec, bspec
bspec, cspec
cspec) = do
    UnionM a
a1 <- aspec -> m (UnionM a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh aspec
aspec
    UnionM b
b1 <- bspec -> m (UnionM b)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh bspec
bspec
    UnionM c
c1 <- cspec -> m (UnionM c)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh cspec
cspec
    UnionM (a, b, c) -> m (UnionM (a, b, c))
forall (m :: * -> *) a. Monad m => a -> m a
return (UnionM (a, b, c) -> m (UnionM (a, b, c)))
-> UnionM (a, b, c) -> m (UnionM (a, b, c))
forall a b. (a -> b) -> a -> b
$ do
      a
ax <- UnionM a
a1
      b
bx <- UnionM b
b1
      c
cx <- UnionM c
c1
      (a, b, c) -> UnionM (a, b, c)
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (a
ax, b
bx, c
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
simpleFresh aspec
aspec
      m (b -> c -> (a, b, c)) -> m b -> m (c -> (a, b, c))
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
simpleFresh bspec
bspec
      m (c -> (a, b, c)) -> m c -> m (a, b, c)
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
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 (UnionM (a, b, c))
fresh = () -> m (UnionM (a, b, c))
forall bool a (m :: * -> *) u.
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (UnionM 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 (UnionM (a, b, c, d))
fresh (aspec
aspec, bspec
bspec, cspec
cspec, dspec
dspec) = do
    UnionM a
a1 <- aspec -> m (UnionM a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh aspec
aspec
    UnionM b
b1 <- bspec -> m (UnionM b)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh bspec
bspec
    UnionM c
c1 <- cspec -> m (UnionM c)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh cspec
cspec
    UnionM d
d1 <- dspec -> m (UnionM d)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh dspec
dspec
    UnionM (a, b, c, d) -> m (UnionM (a, b, c, d))
forall (m :: * -> *) a. Monad m => a -> m a
return (UnionM (a, b, c, d) -> m (UnionM (a, b, c, d)))
-> UnionM (a, b, c, d) -> m (UnionM (a, b, c, d))
forall a b. (a -> b) -> a -> b
$ do
      a
ax <- UnionM a
a1
      b
bx <- UnionM b
b1
      c
cx <- UnionM c
c1
      d
dx <- UnionM d
d1
      (a, b, c, d) -> UnionM (a, b, c, d)
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (a
ax, b
bx, c
cx, d
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
simpleFresh aspec
aspec
      m (b -> c -> d -> (a, b, c, d))
-> m b -> m (c -> d -> (a, b, c, d))
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
simpleFresh bspec
bspec
      m (c -> d -> (a, b, c, d)) -> m c -> m (d -> (a, b, c, d))
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
simpleFresh cspec
cspec
      m (d -> (a, b, c, d)) -> m d -> m (a, b, c, d)
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
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 (UnionM (a, b, c, d))
fresh = () -> m (UnionM (a, b, c, d))
forall bool a (m :: * -> *) u.
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (UnionM 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 (UnionM (a, b, c, d, e))
fresh (aspec
aspec, bspec
bspec, cspec
cspec, dspec
dspec, espec
espec) = do
    UnionM a
a1 <- aspec -> m (UnionM a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh aspec
aspec
    UnionM b
b1 <- bspec -> m (UnionM b)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh bspec
bspec
    UnionM c
c1 <- cspec -> m (UnionM c)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh cspec
cspec
    UnionM d
d1 <- dspec -> m (UnionM d)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh dspec
dspec
    UnionM e
e1 <- espec -> m (UnionM e)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh espec
espec
    UnionM (a, b, c, d, e) -> m (UnionM (a, b, c, d, e))
forall (m :: * -> *) a. Monad m => a -> m a
return (UnionM (a, b, c, d, e) -> m (UnionM (a, b, c, d, e)))
-> UnionM (a, b, c, d, e) -> m (UnionM (a, b, c, d, e))
forall a b. (a -> b) -> a -> b
$ do
      a
ax <- UnionM a
a1
      b
bx <- UnionM b
b1
      c
cx <- UnionM c
c1
      d
dx <- UnionM d
d1
      e
ex <- UnionM e
e1
      (a, b, c, d, e) -> UnionM (a, b, c, d, e)
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (a
ax, b
bx, c
cx, d
dx, e
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
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 (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
simpleFresh bspec
bspec
      m (c -> d -> e -> (a, b, c, d, e))
-> m c -> m (d -> e -> (a, b, c, d, e))
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
simpleFresh cspec
cspec
      m (d -> e -> (a, b, c, d, e)) -> m d -> m (e -> (a, b, c, d, e))
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
simpleFresh dspec
dspec
      m (e -> (a, b, c, d, e)) -> m e -> m (a, b, c, d, e)
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
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 (UnionM (a, b, c, d, e))
fresh = () -> m (UnionM (a, b, c, d, e))
forall bool a (m :: * -> *) u.
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (UnionM 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 (UnionM (a, b, c, d, e, f))
fresh (aspec
aspec, bspec
bspec, cspec
cspec, dspec
dspec, espec
espec, fspec
fspec) = do
    UnionM a
a1 <- aspec -> m (UnionM a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh aspec
aspec
    UnionM b
b1 <- bspec -> m (UnionM b)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh bspec
bspec
    UnionM c
c1 <- cspec -> m (UnionM c)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh cspec
cspec
    UnionM d
d1 <- dspec -> m (UnionM d)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh dspec
dspec
    UnionM e
e1 <- espec -> m (UnionM e)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh espec
espec
    UnionM f
f1 <- fspec -> m (UnionM f)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh fspec
fspec
    UnionM (a, b, c, d, e, f) -> m (UnionM (a, b, c, d, e, f))
forall (m :: * -> *) a. Monad m => a -> m a
return (UnionM (a, b, c, d, e, f) -> m (UnionM (a, b, c, d, e, f)))
-> UnionM (a, b, c, d, e, f) -> m (UnionM (a, b, c, d, e, f))
forall a b. (a -> b) -> a -> b
$ do
      a
ax <- UnionM a
a1
      b
bx <- UnionM b
b1
      c
cx <- UnionM c
c1
      d
dx <- UnionM d
d1
      e
ex <- UnionM e
e1
      f
fx <- UnionM f
f1
      (a, b, c, d, e, f) -> UnionM (a, b, c, d, e, f)
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (a
ax, b
bx, c
cx, d
dx, e
ex, f
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
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 (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
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 (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
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 (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
simpleFresh dspec
dspec
      m (e -> f -> (a, b, c, d, e, f))
-> m e -> m (f -> (a, b, c, d, e, f))
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
simpleFresh espec
espec
      m (f -> (a, b, c, d, e, f)) -> m f -> m (a, b, c, d, e, f)
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
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 (UnionM (a, b, c, d, e, f))
fresh = () -> m (UnionM (a, b, c, d, e, f))
forall bool a (m :: * -> *) u.
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (UnionM 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 (UnionM (a, b, c, d, e, f, g))
fresh (aspec
aspec, bspec
bspec, cspec
cspec, dspec
dspec, espec
espec, fspec
fspec, gspec
gspec) = do
    UnionM a
a1 <- aspec -> m (UnionM a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh aspec
aspec
    UnionM b
b1 <- bspec -> m (UnionM b)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh bspec
bspec
    UnionM c
c1 <- cspec -> m (UnionM c)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh cspec
cspec
    UnionM d
d1 <- dspec -> m (UnionM d)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh dspec
dspec
    UnionM e
e1 <- espec -> m (UnionM e)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh espec
espec
    UnionM f
f1 <- fspec -> m (UnionM f)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh fspec
fspec
    UnionM g
g1 <- gspec -> m (UnionM g)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh gspec
gspec
    UnionM (a, b, c, d, e, f, g) -> m (UnionM (a, b, c, d, e, f, g))
forall (m :: * -> *) a. Monad m => a -> m a
return (UnionM (a, b, c, d, e, f, g) -> m (UnionM (a, b, c, d, e, f, g)))
-> UnionM (a, b, c, d, e, f, g) -> m (UnionM (a, b, c, d, e, f, g))
forall a b. (a -> b) -> a -> b
$ do
      a
ax <- UnionM a
a1
      b
bx <- UnionM b
b1
      c
cx <- UnionM c
c1
      d
dx <- UnionM d
d1
      e
ex <- UnionM e
e1
      f
fx <- UnionM f
f1
      g
gx <- UnionM g
g1
      (a, b, c, d, e, f, g) -> UnionM (a, b, c, d, e, f, g)
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (a
ax, b
bx, c
cx, d
dx, e
ex, f
fx, g
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
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 (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
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 (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
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 (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
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 (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
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 (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
simpleFresh fspec
fspec
      m (g -> (a, b, c, d, e, f, g)) -> m g -> m (a, b, c, d, e, f, g)
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
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 (UnionM (a, b, c, d, e, f, g))
fresh = () -> m (UnionM (a, b, c, d, e, f, g))
forall bool a (m :: * -> *) u.
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (UnionM 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 (UnionM (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
    UnionM a
a1 <- aspec -> m (UnionM a)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh aspec
aspec
    UnionM b
b1 <- bspec -> m (UnionM b)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh bspec
bspec
    UnionM c
c1 <- cspec -> m (UnionM c)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh cspec
cspec
    UnionM d
d1 <- dspec -> m (UnionM d)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh dspec
dspec
    UnionM e
e1 <- espec -> m (UnionM e)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh espec
espec
    UnionM f
f1 <- fspec -> m (UnionM f)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh fspec
fspec
    UnionM g
g1 <- gspec -> m (UnionM g)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh gspec
gspec
    UnionM h
h1 <- hspec -> m (UnionM h)
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh hspec
hspec
    UnionM (a, b, c, d, e, f, g, h)
-> m (UnionM (a, b, c, d, e, f, g, h))
forall (m :: * -> *) a. Monad m => a -> m a
return (UnionM (a, b, c, d, e, f, g, h)
 -> m (UnionM (a, b, c, d, e, f, g, h)))
-> UnionM (a, b, c, d, e, f, g, h)
-> m (UnionM (a, b, c, d, e, f, g, h))
forall a b. (a -> b) -> a -> b
$ do
      a
ax <- UnionM a
a1
      b
bx <- UnionM b
b1
      c
cx <- UnionM c
c1
      d
dx <- UnionM d
d1
      e
ex <- UnionM e
e1
      f
fx <- UnionM f
f1
      g
gx <- UnionM g
g1
      h
hx <- UnionM h
h1
      (a, b, c, d, e, f, g, h) -> UnionM (a, b, c, d, e, f, g, h)
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (a
ax, b
bx, c
cx, d
dx, e
ex, f
fx, g
gx, h
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
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 (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
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 (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
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 (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
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 (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
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 (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
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 (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
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 (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
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 (UnionM (a, b, c, d, e, f, g, h))
fresh = () -> m (UnionM (a, b, c, d, e, f, g, h))
forall bool a (m :: * -> *) u.
(Generic a, GenSymNoSpec (Rep a), Mergeable a, MonadFresh m) =>
() -> m (UnionM 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 (UnionM (MaybeT m a))
fresh spec
v = do
    UnionM (m (Maybe a))
x <- spec -> m (UnionM (m (Maybe a)))
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh spec
v
    UnionM (MaybeT m a) -> m (UnionM (MaybeT m a))
forall (m :: * -> *) a. Monad m => a -> m a
return (UnionM (MaybeT m a) -> m (UnionM (MaybeT m a)))
-> UnionM (MaybeT m a) -> m (UnionM (MaybeT m a))
forall a b. (a -> b) -> a -> b
$ UnionM (MaybeT m a) -> UnionM (MaybeT m a)
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => u a -> u a
merge (UnionM (MaybeT m a) -> UnionM (MaybeT m a))
-> (UnionM (m (Maybe a)) -> UnionM (MaybeT m a))
-> UnionM (m (Maybe a))
-> UnionM (MaybeT m a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (m (Maybe a) -> MaybeT m a)
-> UnionM (m (Maybe a)) -> UnionM (MaybeT m a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap m (Maybe a) -> MaybeT m a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (UnionM (m (Maybe a)) -> UnionM (MaybeT m a))
-> UnionM (m (Maybe a)) -> UnionM (MaybeT m a)
forall a b. (a -> b) -> a -> b
$ UnionM (m (Maybe a))
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
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
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 (UnionM (ExceptT a m b))
fresh spec
v = do
    UnionM (m (Either a b))
x <- spec -> m (UnionM (m (Either a b)))
forall spec a (m :: * -> *).
(GenSym spec a, MonadFresh m) =>
spec -> m (UnionM a)
fresh spec
v
    UnionM (ExceptT a m b) -> m (UnionM (ExceptT a m b))
forall (m :: * -> *) a. Monad m => a -> m a
return (UnionM (ExceptT a m b) -> m (UnionM (ExceptT a m b)))
-> UnionM (ExceptT a m b) -> m (UnionM (ExceptT a m b))
forall a b. (a -> b) -> a -> b
$ UnionM (ExceptT a m b) -> UnionM (ExceptT a m b)
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => u a -> u a
merge (UnionM (ExceptT a m b) -> UnionM (ExceptT a m b))
-> (UnionM (m (Either a b)) -> UnionM (ExceptT a m b))
-> UnionM (m (Either a b))
-> UnionM (ExceptT a m b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (m (Either a b) -> ExceptT a m b)
-> UnionM (m (Either a b)) -> UnionM (ExceptT a m b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap m (Either a b) -> ExceptT a m b
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT (UnionM (m (Either a b)) -> UnionM (ExceptT a m b))
-> UnionM (m (Either a b)) -> UnionM (ExceptT a m b)
forall a b. (a -> b) -> a -> b
$ UnionM (m (Either a b))
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
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
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)

instance (SupportedPrim a) => GenSym (Sym a) (Sym a)

instance (SupportedPrim a) => GenSymSimple (Sym a) (Sym a) where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => Sym a -> m (Sym a)
simpleFresh Sym a
_ = () -> m (Sym a)
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
simpleFresh ()

instance (SupportedPrim a) => GenSym () (Sym a) where
  fresh :: forall (m :: * -> *). MonadFresh m => () -> m (UnionM (Sym a))
fresh ()
_ = Sym a -> UnionM (Sym a)
forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle (Sym a -> UnionM (Sym a)) -> m (Sym a) -> m (UnionM (Sym a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> () -> m (Sym a)
forall spec a (m :: * -> *).
(GenSymSimple spec a, MonadFresh m) =>
spec -> m a
simpleFresh ()

instance (SupportedPrim a) => GenSymSimple () (Sym a) where
  simpleFresh :: forall (m :: * -> *). MonadFresh m => () -> m (Sym a)
simpleFresh ()
_ = do
    FreshIdent
ident <- m FreshIdent
forall (m :: * -> *). MonadFresh m => m FreshIdent
getFreshIdent
    FreshIndex Int
i <- m FreshIndex
forall (m :: * -> *). MonadFresh m => m FreshIndex
nextFreshIndex
    case FreshIdent
ident of
      FreshIdent String
s -> Sym a -> m (Sym a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Sym a -> m (Sym a)) -> Sym a -> m (Sym a)
forall a b. (a -> b) -> a -> b
$ String -> Int -> Sym a
forall c t. Solvable c t => String -> Int -> t
isym String
s Int
i
      FreshIdentWithInfo String
s a
info -> Sym a -> m (Sym a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Sym a -> m (Sym a)) -> Sym a -> m (Sym a)
forall a b. (a -> b) -> a -> b
$ String -> Int -> a -> Sym a
forall c t a.
(Solvable c t, Typeable a, Ord a, Lift a, NFData a, Show a,
 Hashable a) =>
String -> Int -> a -> t
iinfosym String
s Int
i a
info