{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DerivingVia #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}

-- |
-- Module      :   Grisette.Internal.Core.Data.Class.SimpleMergeable
-- Copyright   :   (c) Sirui Lu 2021-2024
-- License     :   BSD-3-Clause (see the LICENSE file)
--
-- Maintainer  :   siruilu@cs.washington.edu
-- Stability   :   Experimental
-- Portability :   GHC only
module Grisette.Internal.Core.Data.Class.SimpleMergeable
  ( -- * Simple mergeable types
    SimpleMergeable (..),
    SimpleMergeable1 (..),
    mrgIte1,
    SimpleMergeable2 (..),
    mrgIte2,

    -- * Generic 'SimpleMergeable'
    SimpleMergeableArgs (..),
    GSimpleMergeable (..),
    genericMrgIte,
    genericLiftMrgIte,

    -- * Symbolic branching
    SymBranching (..),
    mrgIf,
    mergeWithStrategy,
    merge,
  )
where

import Control.Monad.Except (ExceptT (ExceptT))
import Control.Monad.Identity
  ( Identity (Identity),
    IdentityT (IdentityT),
  )
import qualified Control.Monad.RWS.Lazy as RWSLazy
import qualified Control.Monad.RWS.Strict as RWSStrict
import Control.Monad.Reader (ReaderT (ReaderT))
import qualified Control.Monad.State.Lazy as StateLazy
import qualified Control.Monad.State.Strict as StateStrict
import Control.Monad.Trans.Cont (ContT (ContT))
import Control.Monad.Trans.Maybe (MaybeT (MaybeT))
import qualified Control.Monad.Writer.Lazy as WriterLazy
import qualified Control.Monad.Writer.Strict as WriterStrict
import Data.Functor.Compose (Compose (Compose))
import Data.Functor.Const (Const)
import Data.Functor.Product (Product)
import Data.Kind (Type)
import Data.Monoid (Alt, Ap, Endo (Endo))
import qualified Data.Monoid as Monoid
import Data.Ord (Down)
import GHC.Generics
  ( Generic (Rep, from, to),
    Generic1 (Rep1, from1, to1),
    K1 (K1),
    M1 (M1),
    Par1 (Par1),
    Rec1 (Rec1),
    U1,
    V1,
    (:.:) (Comp1),
    type (:*:) ((:*:)),
  )
import GHC.TypeNats (KnownNat, type (<=))
import Generics.Deriving (Default (Default), Default1 (Default1))
import Grisette.Internal.Core.Control.Exception (AssertionError)
import Grisette.Internal.Core.Data.Class.ITEOp (ITEOp (symIte))
import Grisette.Internal.Core.Data.Class.Mergeable
  ( GMergeable,
    Mergeable (rootStrategy),
    Mergeable1 (liftRootStrategy),
    Mergeable2 (liftRootStrategy2),
    Mergeable3 (liftRootStrategy3),
    MergingStrategy (SimpleStrategy),
  )
import Grisette.Internal.Core.Data.Class.TryMerge
  ( TryMerge (tryMergeWithStrategy),
  )
import Grisette.Internal.SymPrim.FP (ValidFP)
import Grisette.Internal.SymPrim.GeneralFun (type (-->))
import Grisette.Internal.SymPrim.Prim.Term
  ( LinkedRep,
    SupportedPrim,
  )
import Grisette.Internal.SymPrim.SymBV
  ( SymIntN,
    SymWordN,
  )
import Grisette.Internal.SymPrim.SymBool (SymBool)
import Grisette.Internal.SymPrim.SymFP (SymFP, SymFPRoundingMode)
import Grisette.Internal.SymPrim.SymGeneralFun (type (-~>))
import Grisette.Internal.SymPrim.SymInteger (SymInteger)
import Grisette.Internal.SymPrim.SymTabularFun (type (=~>))
import Grisette.Internal.SymPrim.TabularFun (type (=->))
import Grisette.Internal.TH.DeriveBuiltin (deriveBuiltins)
import Grisette.Internal.TH.DeriveInstanceProvider
  ( Strategy (ViaDefault, ViaDefault1),
  )
import Grisette.Internal.Utils.Derive (Arity0, Arity1)

-- $setup
-- >>> import Grisette.Core
-- >>> import Grisette.SymPrim
-- >>> import Control.Monad.Identity

-- | This class indicates that a type has a simple root merge strategy.
--
-- __Note:__ This type class can be derived for algebraic data types.
-- You may need the @DerivingVia@ and @DerivingStrategies@ extensions.
--
-- > data X = ...
-- >   deriving Generic
-- >   deriving (Mergeable, SimpleMergeable) via (Default X)
class (Mergeable a) => SimpleMergeable a where
  -- | Performs if-then-else with the simple root merge strategy.
  --
  -- >>> mrgIte "a" "b" "c" :: SymInteger
  -- (ite a b c)
  mrgIte :: SymBool -> a -> a -> a

-- | Lifting of the 'SimpleMergeable' class to unary type constructors.
class
  (Mergeable1 u, forall a. (SimpleMergeable a) => (SimpleMergeable (u a))) =>
  SimpleMergeable1 u
  where
  -- | Lift 'mrgIte' through the type constructor.
  --
  -- >>> liftMrgIte mrgIte "a" (Identity "b") (Identity "c") :: Identity SymInteger
  -- Identity (ite a b c)
  liftMrgIte :: (SymBool -> a -> a -> a) -> SymBool -> u a -> u a -> u a

-- | Lift the standard 'mrgIte' function through the type constructor.
--
-- >>> mrgIte1 "a" (Identity "b") (Identity "c") :: Identity SymInteger
-- Identity (ite a b c)
mrgIte1 ::
  (SimpleMergeable1 u, SimpleMergeable a) => SymBool -> u a -> u a -> u a
mrgIte1 :: forall (u :: * -> *) a.
(SimpleMergeable1 u, SimpleMergeable a) =>
SymBool -> u a -> u a -> u a
mrgIte1 = (SymBool -> a -> a -> a) -> SymBool -> u a -> u a -> u a
forall a. (SymBool -> a -> a -> a) -> SymBool -> u a -> u a -> u a
forall (u :: * -> *) a.
SimpleMergeable1 u =>
(SymBool -> a -> a -> a) -> SymBool -> u a -> u a -> u a
liftMrgIte SymBool -> a -> a -> a
forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte
{-# INLINE mrgIte1 #-}

-- | Lifting of the 'SimpleMergeable' class to binary type constructors.
class
  (Mergeable2 u, forall a. (SimpleMergeable a) => SimpleMergeable1 (u a)) =>
  SimpleMergeable2 u
  where
  -- | Lift 'mrgIte' through the type constructor.
  --
  -- >>> liftMrgIte2 mrgIte mrgIte "a" ("b", "c") ("d", "e") :: (SymInteger, SymBool)
  -- ((ite a b d),(ite a c e))
  liftMrgIte2 ::
    (SymBool -> a -> a -> a) ->
    (SymBool -> b -> b -> b) ->
    SymBool ->
    u a b ->
    u a b ->
    u a b

-- | Lift the standard 'mrgIte' function through the type constructor.
--
-- >>> mrgIte2 "a" ("b", "c") ("d", "e") :: (SymInteger, SymBool)
-- ((ite a b d),(ite a c e))
mrgIte2 ::
  (SimpleMergeable2 u, SimpleMergeable a, SimpleMergeable b) =>
  SymBool ->
  u a b ->
  u a b ->
  u a b
mrgIte2 :: forall (u :: * -> * -> *) a b.
(SimpleMergeable2 u, SimpleMergeable a, SimpleMergeable b) =>
SymBool -> u a b -> u a b -> u a b
mrgIte2 = (SymBool -> a -> a -> a)
-> (SymBool -> b -> b -> b) -> SymBool -> u a b -> u a b -> u a b
forall a b.
(SymBool -> a -> a -> a)
-> (SymBool -> b -> b -> b) -> SymBool -> u a b -> u a b -> u a b
forall (u :: * -> * -> *) a b.
SimpleMergeable2 u =>
(SymBool -> a -> a -> a)
-> (SymBool -> b -> b -> b) -> SymBool -> u a b -> u a b -> u a b
liftMrgIte2 SymBool -> a -> a -> a
forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool -> b -> b -> b
forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte
{-# INLINE mrgIte2 #-}

-- | The arguments to the generic simple merging function.
data family SimpleMergeableArgs arity a :: Type

data instance SimpleMergeableArgs Arity0 _ = SimpleMergeableArgs0

newtype instance SimpleMergeableArgs Arity1 a
  = SimpleMergeableArgs1 (SymBool -> a -> a -> a)

-- | Generic 'SimpleMergeable' class.
class GSimpleMergeable arity f where
  gmrgIte :: SimpleMergeableArgs arity a -> SymBool -> f a -> f a -> f a

instance GSimpleMergeable arity V1 where
  gmrgIte :: forall a.
SimpleMergeableArgs arity a -> SymBool -> V1 a -> V1 a -> V1 a
gmrgIte SimpleMergeableArgs arity a
_ SymBool
_ V1 a
t V1 a
_ = V1 a
t
  {-# INLINE gmrgIte #-}

instance (GSimpleMergeable arity U1) where
  gmrgIte :: forall a.
SimpleMergeableArgs arity a -> SymBool -> U1 a -> U1 a -> U1 a
gmrgIte SimpleMergeableArgs arity a
_ SymBool
_ U1 a
t U1 a
_ = U1 a
t
  {-# INLINE gmrgIte #-}

instance
  (GSimpleMergeable arity a, GSimpleMergeable arity b) =>
  (GSimpleMergeable arity (a :*: b))
  where
  gmrgIte :: forall a.
SimpleMergeableArgs arity a
-> SymBool -> (:*:) a b a -> (:*:) a b a -> (:*:) a b a
gmrgIte SimpleMergeableArgs arity a
args SymBool
cond (a a
a1 :*: b a
a2) (a a
b1 :*: b a
b2) =
    SimpleMergeableArgs arity a -> SymBool -> a a -> a a -> a a
forall a.
SimpleMergeableArgs arity a -> SymBool -> a a -> a a -> a a
forall arity (f :: * -> *) a.
GSimpleMergeable arity f =>
SimpleMergeableArgs arity a -> SymBool -> f a -> f a -> f a
gmrgIte SimpleMergeableArgs arity a
args SymBool
cond a a
a1 a a
b1 a a -> b a -> (:*:) a b a
forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
:*: SimpleMergeableArgs arity a -> SymBool -> b a -> b a -> b a
forall a.
SimpleMergeableArgs arity a -> SymBool -> b a -> b a -> b a
forall arity (f :: * -> *) a.
GSimpleMergeable arity f =>
SimpleMergeableArgs arity a -> SymBool -> f a -> f a -> f a
gmrgIte SimpleMergeableArgs arity a
args SymBool
cond b a
a2 b a
b2
  {-# INLINE gmrgIte #-}

instance (GSimpleMergeable arity a) => (GSimpleMergeable arity (M1 i c a)) where
  gmrgIte :: forall a.
SimpleMergeableArgs arity a
-> SymBool -> M1 i c a a -> M1 i c a a -> M1 i c a a
gmrgIte SimpleMergeableArgs arity a
args SymBool
cond (M1 a a
a) (M1 a a
b) = a a -> M1 i c a a
forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 (a a -> M1 i c a a) -> a a -> M1 i c a a
forall a b. (a -> b) -> a -> b
$ SimpleMergeableArgs arity a -> SymBool -> a a -> a a -> a a
forall a.
SimpleMergeableArgs arity a -> SymBool -> a a -> a a -> a a
forall arity (f :: * -> *) a.
GSimpleMergeable arity f =>
SimpleMergeableArgs arity a -> SymBool -> f a -> f a -> f a
gmrgIte SimpleMergeableArgs arity a
args SymBool
cond a a
a a a
b
  {-# INLINE gmrgIte #-}

instance (SimpleMergeable c) => (GSimpleMergeable arity (K1 i c)) where
  gmrgIte :: forall a.
SimpleMergeableArgs arity a
-> SymBool -> K1 i c a -> K1 i c a -> K1 i c a
gmrgIte SimpleMergeableArgs arity a
_ SymBool
cond (K1 c
a) (K1 c
b) = c -> K1 i c a
forall k i c (p :: k). c -> K1 i c p
K1 (c -> K1 i c a) -> c -> K1 i c a
forall a b. (a -> b) -> a -> b
$ SymBool -> c -> c -> c
forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond c
a c
b
  {-# INLINE gmrgIte #-}

instance GSimpleMergeable Arity1 Par1 where
  gmrgIte :: forall a.
SimpleMergeableArgs Arity1 a
-> SymBool -> Par1 a -> Par1 a -> Par1 a
gmrgIte (SimpleMergeableArgs1 SymBool -> a -> a -> a
f) SymBool
cond (Par1 a
l) (Par1 a
r) = a -> Par1 a
forall p. p -> Par1 p
Par1 (a -> Par1 a) -> a -> Par1 a
forall a b. (a -> b) -> a -> b
$ SymBool -> a -> a -> a
f SymBool
cond a
l a
r
  {-# INLINE gmrgIte #-}

instance (SimpleMergeable1 f) => GSimpleMergeable Arity1 (Rec1 f) where
  gmrgIte :: forall a.
SimpleMergeableArgs Arity1 a
-> SymBool -> Rec1 f a -> Rec1 f a -> Rec1 f a
gmrgIte (SimpleMergeableArgs1 SymBool -> a -> a -> a
f) SymBool
cond (Rec1 f a
l) (Rec1 f a
r) =
    f a -> Rec1 f a
forall k (f :: k -> *) (p :: k). f p -> Rec1 f p
Rec1 (f a -> Rec1 f a) -> f a -> Rec1 f a
forall a b. (a -> b) -> a -> b
$ (SymBool -> a -> a -> a) -> SymBool -> f a -> f a -> f a
forall a. (SymBool -> a -> a -> a) -> SymBool -> f a -> f a -> f a
forall (u :: * -> *) a.
SimpleMergeable1 u =>
(SymBool -> a -> a -> a) -> SymBool -> u a -> u a -> u a
liftMrgIte SymBool -> a -> a -> a
f SymBool
cond f a
l f a
r
  {-# INLINE gmrgIte #-}

instance
  (SimpleMergeable1 f, GSimpleMergeable Arity1 g) =>
  GSimpleMergeable Arity1 (f :.: g)
  where
  gmrgIte :: forall a.
SimpleMergeableArgs Arity1 a
-> SymBool -> (:.:) f g a -> (:.:) f g a -> (:.:) f g a
gmrgIte SimpleMergeableArgs Arity1 a
targs SymBool
cond (Comp1 f (g a)
l) (Comp1 f (g a)
r) =
    f (g a) -> (:.:) f g a
forall k2 k1 (f :: k2 -> *) (g :: k1 -> k2) (p :: k1).
f (g p) -> (:.:) f g p
Comp1 (f (g a) -> (:.:) f g a) -> f (g a) -> (:.:) f g a
forall a b. (a -> b) -> a -> b
$ (SymBool -> g a -> g a -> g a)
-> SymBool -> f (g a) -> f (g a) -> f (g a)
forall a. (SymBool -> a -> a -> a) -> SymBool -> f a -> f a -> f a
forall (u :: * -> *) a.
SimpleMergeable1 u =>
(SymBool -> a -> a -> a) -> SymBool -> u a -> u a -> u a
liftMrgIte (SimpleMergeableArgs Arity1 a -> SymBool -> g a -> g a -> g a
forall a.
SimpleMergeableArgs Arity1 a -> SymBool -> g a -> g a -> g a
forall arity (f :: * -> *) a.
GSimpleMergeable arity f =>
SimpleMergeableArgs arity a -> SymBool -> f a -> f a -> f a
gmrgIte SimpleMergeableArgs Arity1 a
targs) SymBool
cond f (g a)
l f (g a)
r
  {-# INLINE gmrgIte #-}

instance
  (Generic a, GSimpleMergeable Arity0 (Rep a), GMergeable Arity0 (Rep a)) =>
  SimpleMergeable (Default a)
  where
  mrgIte :: SymBool -> Default a -> Default a -> Default a
mrgIte SymBool
cond (Default a
a) (Default a
b) =
    a -> Default a
forall a. a -> Default a
Default (a -> Default a) -> a -> Default a
forall a b. (a -> b) -> a -> b
$ SymBool -> a -> a -> a
forall a.
(Generic a, GSimpleMergeable Arity0 (Rep a)) =>
SymBool -> a -> a -> a
genericMrgIte SymBool
cond a
a a
b
  {-# INLINE mrgIte #-}

-- | Generic 'mrgIte' function.
genericMrgIte ::
  (Generic a, GSimpleMergeable Arity0 (Rep a)) =>
  SymBool ->
  a ->
  a ->
  a
genericMrgIte :: forall a.
(Generic a, GSimpleMergeable Arity0 (Rep a)) =>
SymBool -> a -> a -> a
genericMrgIte SymBool
cond a
a a
b =
  Rep a Any -> a
forall a x. Generic a => Rep a x -> a
forall x. Rep a x -> a
to (Rep a Any -> a) -> Rep a Any -> a
forall a b. (a -> b) -> a -> b
$ SimpleMergeableArgs Arity0 Any
-> SymBool -> Rep a Any -> Rep a Any -> Rep a Any
forall a.
SimpleMergeableArgs Arity0 a
-> SymBool -> Rep a a -> Rep a a -> Rep a a
forall arity (f :: * -> *) a.
GSimpleMergeable arity f =>
SimpleMergeableArgs arity a -> SymBool -> f a -> f a -> f a
gmrgIte SimpleMergeableArgs Arity0 Any
forall _. SimpleMergeableArgs Arity0 _
SimpleMergeableArgs0 SymBool
cond (a -> Rep a Any
forall x. a -> Rep a x
forall a x. Generic a => a -> Rep a x
from a
a) (a -> Rep a Any
forall x. a -> Rep a x
forall a x. Generic a => a -> Rep a x
from a
b)
{-# INLINE genericMrgIte #-}

instance
  ( Generic1 f,
    GSimpleMergeable Arity1 (Rep1 f),
    GMergeable Arity1 (Rep1 f),
    SimpleMergeable a
  ) =>
  SimpleMergeable (Default1 f a)
  where
  mrgIte :: SymBool -> Default1 f a -> Default1 f a -> Default1 f a
mrgIte = SymBool -> Default1 f a -> Default1 f a -> Default1 f a
forall (u :: * -> *) a.
(SimpleMergeable1 u, SimpleMergeable a) =>
SymBool -> u a -> u a -> u a
mrgIte1
  {-# INLINE mrgIte #-}

instance
  (Generic1 f, GSimpleMergeable Arity1 (Rep1 f), GMergeable Arity1 (Rep1 f)) =>
  SimpleMergeable1 (Default1 f)
  where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a)
-> SymBool -> Default1 f a -> Default1 f a -> Default1 f a
liftMrgIte SymBool -> a -> a -> a
f SymBool
c (Default1 f a
l) (Default1 f a
r) =
    f a -> Default1 f a
forall (f :: * -> *) a. f a -> Default1 f a
Default1 (f a -> Default1 f a) -> f a -> Default1 f a
forall a b. (a -> b) -> a -> b
$ (SymBool -> a -> a -> a) -> SymBool -> f a -> f a -> f a
forall (f :: * -> *) a.
(Generic1 f, GSimpleMergeable Arity1 (Rep1 f)) =>
(SymBool -> a -> a -> a) -> SymBool -> f a -> f a -> f a
genericLiftMrgIte SymBool -> a -> a -> a
f SymBool
c f a
l f a
r
  {-# INLINE liftMrgIte #-}

-- | Generic 'liftMrgIte' function.
genericLiftMrgIte ::
  (Generic1 f, GSimpleMergeable Arity1 (Rep1 f)) =>
  (SymBool -> a -> a -> a) ->
  SymBool ->
  f a ->
  f a ->
  f a
genericLiftMrgIte :: forall (f :: * -> *) a.
(Generic1 f, GSimpleMergeable Arity1 (Rep1 f)) =>
(SymBool -> a -> a -> a) -> SymBool -> f a -> f a -> f a
genericLiftMrgIte SymBool -> a -> a -> a
f SymBool
c f a
l f a
r =
  Rep1 f a -> f a
forall a. Rep1 f a -> f a
forall k (f :: k -> *) (a :: k). Generic1 f => Rep1 f a -> f a
to1 (Rep1 f a -> f a) -> Rep1 f a -> f a
forall a b. (a -> b) -> a -> b
$ SimpleMergeableArgs Arity1 a
-> SymBool -> Rep1 f a -> Rep1 f a -> Rep1 f a
forall a.
SimpleMergeableArgs Arity1 a
-> SymBool -> Rep1 f a -> Rep1 f a -> Rep1 f a
forall arity (f :: * -> *) a.
GSimpleMergeable arity f =>
SimpleMergeableArgs arity a -> SymBool -> f a -> f a -> f a
gmrgIte ((SymBool -> a -> a -> a) -> SimpleMergeableArgs Arity1 a
forall a. (SymBool -> a -> a -> a) -> SimpleMergeableArgs Arity1 a
SimpleMergeableArgs1 SymBool -> a -> a -> a
f) SymBool
c (f a -> Rep1 f a
forall a. f a -> Rep1 f a
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1 f a
l) (f a -> Rep1 f a
forall a. f a -> Rep1 f a
forall k (f :: k -> *) (a :: k). Generic1 f => f a -> Rep1 f a
from1 f a
r)
{-# INLINE genericLiftMrgIte #-}

-- | Special case of the 'Mergeable1' and 'SimpleMergeable1' class for type
-- constructors that are 'SimpleMergeable' when applied to any 'Mergeable'
-- types.
--
-- This type class is used to generalize the 'mrgIf' function to other
-- containers, for example, monad transformer transformed Unions.
class
  ( SimpleMergeable1 u,
    forall a. (Mergeable a) => SimpleMergeable (u a),
    TryMerge u
  ) =>
  SymBranching (u :: Type -> Type)
  where
  -- | Symbolic @if@ control flow with the result merged with some merge
  -- strategy.
  --
  -- >>> mrgIfWithStrategy rootStrategy "a" (mrgSingle "b") (return "c") :: Union SymInteger
  -- {(ite a b c)}
  --
  -- __Note:__ Be careful to call this directly in your code.
  -- The supplied merge strategy should be consistent with the type's root merge
  -- strategy, or some internal invariants would be broken and the program can
  -- crash.
  --
  -- This function is to be called when the 'Mergeable' constraint can not be
  -- resolved, e.g., the merge strategy for the contained type is given with
  -- 'Mergeable1'. In other cases, 'mrgIf' is usually a better alternative.
  mrgIfWithStrategy :: MergingStrategy a -> SymBool -> u a -> u a -> u a

  -- | Symbolic @if@ control flow with the result.
  --
  -- This function does not need a merging strategy, and it will merge the
  -- result only if any of the branches is merged.
  mrgIfPropagatedStrategy :: SymBool -> u a -> u a -> u a

-- | Try to merge the container with a given merge strategy.
mergeWithStrategy :: (SymBranching m) => MergingStrategy a -> m a -> m a
mergeWithStrategy :: forall (m :: * -> *) a.
SymBranching m =>
MergingStrategy a -> m a -> m a
mergeWithStrategy = MergingStrategy a -> m a -> m a
forall a. MergingStrategy a -> m a -> m a
forall (m :: * -> *) a.
TryMerge m =>
MergingStrategy a -> m a -> m a
tryMergeWithStrategy
{-# INLINE mergeWithStrategy #-}

-- | Try to merge the container with the root strategy.
merge :: (SymBranching m, Mergeable a) => m a -> m a
merge :: forall (m :: * -> *) a. (SymBranching m, Mergeable a) => m a -> m a
merge = MergingStrategy a -> m a -> m a
forall (m :: * -> *) a.
SymBranching m =>
MergingStrategy a -> m a -> m a
mergeWithStrategy MergingStrategy a
forall a. Mergeable a => MergingStrategy a
rootStrategy
{-# INLINE merge #-}

-- | Symbolic @if@ control flow with the result merged with the type's root
-- merge strategy.
--
-- Equivalent to @'mrgIfWithStrategy' 'rootStrategy'@.
--
-- >>> mrgIf "a" (return "b") (return "c") :: Union SymInteger
-- {(ite a b c)}
mrgIf :: (SymBranching u, Mergeable a) => SymBool -> u a -> u a -> u a
mrgIf :: forall (u :: * -> *) a.
(SymBranching u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf = MergingStrategy a -> SymBool -> u a -> u a -> u a
forall a. MergingStrategy a -> SymBool -> u a -> u a -> u a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy MergingStrategy a
forall a. Mergeable a => MergingStrategy a
rootStrategy
{-# INLINE mrgIf #-}

deriveBuiltins
  (ViaDefault ''SimpleMergeable)
  [''SimpleMergeable]
  [ ''(),
    ''(,),
    ''(,,),
    ''(,,,),
    ''(,,,,),
    ''(,,,,,),
    ''(,,,,,,),
    ''(,,,,,,,),
    ''(,,,,,,,,),
    ''(,,,,,,,,,),
    ''(,,,,,,,,,,),
    ''(,,,,,,,,,,,),
    ''(,,,,,,,,,,,,),
    ''(,,,,,,,,,,,,,),
    ''(,,,,,,,,,,,,,,),
    ''AssertionError,
    ''Identity,
    ''Monoid.Dual,
    ''Monoid.Sum,
    ''Monoid.Product,
    ''Down
  ]

deriveBuiltins
  (ViaDefault1 ''SimpleMergeable1)
  [''SimpleMergeable, ''SimpleMergeable1]
  [ ''(,),
    ''(,,),
    ''(,,,),
    ''(,,,,),
    ''(,,,,,),
    ''(,,,,,,),
    ''(,,,,,,,),
    ''(,,,,,,,,),
    ''(,,,,,,,,,),
    ''(,,,,,,,,,,),
    ''(,,,,,,,,,,,),
    ''(,,,,,,,,,,,,),
    ''(,,,,,,,,,,,,,),
    ''(,,,,,,,,,,,,,,),
    ''Identity,
    ''Monoid.Dual,
    ''Monoid.Sum,
    ''Monoid.Product,
    ''Down
  ]

instance SimpleMergeable2 (,) where
  liftMrgIte2 :: forall a b.
(SymBool -> a -> a -> a)
-> (SymBool -> b -> b -> b)
-> SymBool
-> (a, b)
-> (a, b)
-> (a, b)
liftMrgIte2 SymBool -> a -> a -> a
ma SymBool -> b -> b -> b
mb SymBool
cond (a
a1, b
b1) (a
a2, b
b2) = (SymBool -> a -> a -> a
ma SymBool
cond a
a1 a
a2, SymBool -> b -> b -> b
mb SymBool
cond b
b1 b
b2)
  {-# INLINE liftMrgIte2 #-}

instance (SimpleMergeable a) => SimpleMergeable2 ((,,) a) where
  liftMrgIte2 :: forall a b.
(SymBool -> a -> a -> a)
-> (SymBool -> b -> b -> b)
-> SymBool
-> (a, a, b)
-> (a, a, b)
-> (a, a, b)
liftMrgIte2 SymBool -> a -> a -> a
mb SymBool -> b -> b -> b
mc SymBool
cond (a
a1, a
b1, b
c1) (a
a2, a
b2, b
c2) =
    (SymBool -> a -> a -> a
forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond a
a1 a
a2, SymBool -> a -> a -> a
mb SymBool
cond a
b1 a
b2, SymBool -> b -> b -> b
mc SymBool
cond b
c1 b
c2)
  {-# INLINE liftMrgIte2 #-}

instance
  (SimpleMergeable a, SimpleMergeable b) =>
  SimpleMergeable2 ((,,,) a b)
  where
  liftMrgIte2 :: forall a b.
(SymBool -> a -> a -> a)
-> (SymBool -> b -> b -> b)
-> SymBool
-> (a, b, a, b)
-> (a, b, a, b)
-> (a, b, a, b)
liftMrgIte2 SymBool -> a -> a -> a
mc SymBool -> b -> b -> b
md SymBool
cond (a
a1, b
b1, a
c1, b
d1) (a
a2, b
b2, a
c2, b
d2) =
    (SymBool -> a -> a -> a
forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond a
a1 a
a2, SymBool -> b -> b -> b
forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond b
b1 b
b2, SymBool -> a -> a -> a
mc SymBool
cond a
c1 a
c2, SymBool -> b -> b -> b
md SymBool
cond b
d1 b
d2)
  {-# INLINE liftMrgIte2 #-}

instance (SimpleMergeable b) => SimpleMergeable (a -> b) where
  mrgIte :: SymBool -> (a -> b) -> (a -> b) -> a -> b
mrgIte = SymBool -> (a -> b) -> (a -> b) -> a -> b
forall (u :: * -> *) a.
(SimpleMergeable1 u, SimpleMergeable a) =>
SymBool -> u a -> u a -> u a
mrgIte1
  {-# INLINE mrgIte #-}

instance SimpleMergeable1 ((->) a) where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a)
-> SymBool -> (a -> a) -> (a -> a) -> a -> a
liftMrgIte SymBool -> a -> a -> a
ms SymBool
cond a -> a
t a -> a
f a
v = SymBool -> a -> a -> a
ms SymBool
cond (a -> a
t a
v) (a -> a
f a
v)
  {-# INLINE liftMrgIte #-}

instance SimpleMergeable2 (->) where
  liftMrgIte2 :: forall a b.
(SymBool -> a -> a -> a)
-> (SymBool -> b -> b -> b)
-> SymBool
-> (a -> b)
-> (a -> b)
-> a -> b
liftMrgIte2 SymBool -> a -> a -> a
_ SymBool -> b -> b -> b
ms SymBool
cond a -> b
t a -> b
f a
v = SymBool -> b -> b -> b
ms SymBool
cond (a -> b
t a
v) (a -> b
f a
v)
  {-# INLINE liftMrgIte2 #-}

-- MaybeT
instance (SymBranching m, Mergeable a) => SimpleMergeable (MaybeT m a) where
  mrgIte :: SymBool -> MaybeT m a -> MaybeT m a -> MaybeT m a
mrgIte = SymBool -> MaybeT m a -> MaybeT m a -> MaybeT m a
forall (u :: * -> *) a.
(SymBranching u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
  {-# INLINE mrgIte #-}

instance (SymBranching m) => SimpleMergeable1 (MaybeT m) where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a)
-> SymBool -> MaybeT m a -> MaybeT m a -> MaybeT m a
liftMrgIte SymBool -> a -> a -> a
m = MergingStrategy a
-> SymBool -> MaybeT m a -> MaybeT m a -> MaybeT m a
forall a.
MergingStrategy a
-> SymBool -> MaybeT m a -> MaybeT m a -> MaybeT m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy ((SymBool -> a -> a -> a) -> MergingStrategy a
forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance (SymBranching m) => SymBranching (MaybeT m) where
  mrgIfWithStrategy :: forall a.
MergingStrategy a
-> SymBool -> MaybeT m a -> MaybeT m a -> MaybeT m a
mrgIfWithStrategy MergingStrategy a
strategy SymBool
cond (MaybeT m (Maybe a)
l) (MaybeT m (Maybe a)
r) =
    m (Maybe a) -> MaybeT m a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m (Maybe a) -> MaybeT m a) -> m (Maybe a) -> MaybeT m a
forall a b. (a -> b) -> a -> b
$ MergingStrategy (Maybe a)
-> SymBool -> m (Maybe a) -> m (Maybe a) -> m (Maybe a)
forall a. MergingStrategy a -> SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (MergingStrategy a -> MergingStrategy (Maybe a)
forall a. MergingStrategy a -> MergingStrategy (Maybe a)
forall (u :: * -> *) a.
Mergeable1 u =>
MergingStrategy a -> MergingStrategy (u a)
liftRootStrategy MergingStrategy a
strategy) SymBool
cond m (Maybe a)
l m (Maybe a)
r
  {-# INLINE mrgIfWithStrategy #-}
  mrgIfPropagatedStrategy :: forall a. SymBool -> MaybeT m a -> MaybeT m a -> MaybeT m a
mrgIfPropagatedStrategy SymBool
cond (MaybeT m (Maybe a)
l) (MaybeT m (Maybe a)
r) =
    m (Maybe a) -> MaybeT m a
forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT (m (Maybe a) -> MaybeT m a) -> m (Maybe a) -> MaybeT m a
forall a b. (a -> b) -> a -> b
$ SymBool -> m (Maybe a) -> m (Maybe a) -> m (Maybe a)
forall a. SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
SymBool -> u a -> u a -> u a
mrgIfPropagatedStrategy SymBool
cond m (Maybe a)
l m (Maybe a)
r
  {-# INLINE mrgIfPropagatedStrategy #-}

-- ExceptT
instance
  (SymBranching m, Mergeable e, Mergeable a) =>
  SimpleMergeable (ExceptT e m a)
  where
  mrgIte :: SymBool -> ExceptT e m a -> ExceptT e m a -> ExceptT e m a
mrgIte = SymBool -> ExceptT e m a -> ExceptT e m a -> ExceptT e m a
forall (u :: * -> *) a.
(SymBranching u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
  {-# INLINE mrgIte #-}

instance
  (SymBranching m, Mergeable e) =>
  SimpleMergeable1 (ExceptT e m)
  where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a)
-> SymBool -> ExceptT e m a -> ExceptT e m a -> ExceptT e m a
liftMrgIte SymBool -> a -> a -> a
m = MergingStrategy a
-> SymBool -> ExceptT e m a -> ExceptT e m a -> ExceptT e m a
forall a.
MergingStrategy a
-> SymBool -> ExceptT e m a -> ExceptT e m a -> ExceptT e m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy ((SymBool -> a -> a -> a) -> MergingStrategy a
forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance
  (SymBranching m, Mergeable e) =>
  SymBranching (ExceptT e m)
  where
  mrgIfWithStrategy :: forall a.
MergingStrategy a
-> SymBool -> ExceptT e m a -> ExceptT e m a -> ExceptT e m a
mrgIfWithStrategy MergingStrategy a
s SymBool
cond (ExceptT m (Either e a)
t) (ExceptT m (Either e a)
f) =
    m (Either e a) -> ExceptT e m a
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT (m (Either e a) -> ExceptT e m a)
-> m (Either e a) -> ExceptT e m a
forall a b. (a -> b) -> a -> b
$ MergingStrategy (Either e a)
-> SymBool -> m (Either e a) -> m (Either e a) -> m (Either e a)
forall a. MergingStrategy a -> SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (MergingStrategy a -> MergingStrategy (Either e a)
forall a. MergingStrategy a -> MergingStrategy (Either e a)
forall (u :: * -> *) a.
Mergeable1 u =>
MergingStrategy a -> MergingStrategy (u a)
liftRootStrategy MergingStrategy a
s) SymBool
cond m (Either e a)
t m (Either e a)
f
  {-# INLINE mrgIfWithStrategy #-}
  mrgIfPropagatedStrategy :: forall a.
SymBool -> ExceptT e m a -> ExceptT e m a -> ExceptT e m a
mrgIfPropagatedStrategy SymBool
cond (ExceptT m (Either e a)
t) (ExceptT m (Either e a)
f) =
    m (Either e a) -> ExceptT e m a
forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT (m (Either e a) -> ExceptT e m a)
-> m (Either e a) -> ExceptT e m a
forall a b. (a -> b) -> a -> b
$ SymBool -> m (Either e a) -> m (Either e a) -> m (Either e a)
forall a. SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
SymBool -> u a -> u a -> u a
mrgIfPropagatedStrategy SymBool
cond m (Either e a)
t m (Either e a)
f
  {-# INLINE mrgIfPropagatedStrategy #-}

-- StateT
instance
  (Mergeable s, Mergeable a, SymBranching m) =>
  SimpleMergeable (StateLazy.StateT s m a)
  where
  mrgIte :: SymBool -> StateT s m a -> StateT s m a -> StateT s m a
mrgIte = SymBool -> StateT s m a -> StateT s m a -> StateT s m a
forall (u :: * -> *) a.
(SymBranching u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
  {-# INLINE mrgIte #-}

instance
  (Mergeable s, SymBranching m) =>
  SimpleMergeable1 (StateLazy.StateT s m)
  where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a)
-> SymBool -> StateT s m a -> StateT s m a -> StateT s m a
liftMrgIte SymBool -> a -> a -> a
m = MergingStrategy a
-> SymBool -> StateT s m a -> StateT s m a -> StateT s m a
forall a.
MergingStrategy a
-> SymBool -> StateT s m a -> StateT s m a -> StateT s m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy ((SymBool -> a -> a -> a) -> MergingStrategy a
forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance
  (Mergeable s, SymBranching m) =>
  SymBranching (StateLazy.StateT s m)
  where
  mrgIfWithStrategy :: forall a.
MergingStrategy a
-> SymBool -> StateT s m a -> StateT s m a -> StateT s m a
mrgIfWithStrategy MergingStrategy a
s SymBool
cond (StateLazy.StateT s -> m (a, s)
t) (StateLazy.StateT s -> m (a, s)
f) =
    (s -> m (a, s)) -> StateT s m a
forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateLazy.StateT ((s -> m (a, s)) -> StateT s m a)
-> (s -> m (a, s)) -> StateT s m a
forall a b. (a -> b) -> a -> b
$ \s
v ->
      MergingStrategy (a, s)
-> SymBool -> m (a, s) -> m (a, s) -> m (a, s)
forall a. MergingStrategy a -> SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy
        (MergingStrategy a -> MergingStrategy s -> MergingStrategy (a, s)
forall a b.
MergingStrategy a -> MergingStrategy b -> MergingStrategy (a, b)
forall (u :: * -> * -> *) a b.
Mergeable2 u =>
MergingStrategy a -> MergingStrategy b -> MergingStrategy (u a b)
liftRootStrategy2 MergingStrategy a
s MergingStrategy s
forall a. Mergeable a => MergingStrategy a
rootStrategy)
        SymBool
cond
        (s -> m (a, s)
t s
v)
        (s -> m (a, s)
f s
v)
  {-# INLINE mrgIfWithStrategy #-}
  mrgIfPropagatedStrategy :: forall a. SymBool -> StateT s m a -> StateT s m a -> StateT s m a
mrgIfPropagatedStrategy SymBool
cond (StateLazy.StateT s -> m (a, s)
t) (StateLazy.StateT s -> m (a, s)
f) =
    (s -> m (a, s)) -> StateT s m a
forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateLazy.StateT ((s -> m (a, s)) -> StateT s m a)
-> (s -> m (a, s)) -> StateT s m a
forall a b. (a -> b) -> a -> b
$ \s
v -> SymBool -> m (a, s) -> m (a, s) -> m (a, s)
forall a. SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
SymBool -> u a -> u a -> u a
mrgIfPropagatedStrategy SymBool
cond (s -> m (a, s)
t s
v) (s -> m (a, s)
f s
v)
  {-# INLINE mrgIfPropagatedStrategy #-}

instance
  (Mergeable s, Mergeable a, SymBranching m) =>
  SimpleMergeable (StateStrict.StateT s m a)
  where
  mrgIte :: SymBool -> StateT s m a -> StateT s m a -> StateT s m a
mrgIte = SymBool -> StateT s m a -> StateT s m a -> StateT s m a
forall (u :: * -> *) a.
(SymBranching u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
  {-# INLINE mrgIte #-}

instance
  (Mergeable s, SymBranching m) =>
  SimpleMergeable1 (StateStrict.StateT s m)
  where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a)
-> SymBool -> StateT s m a -> StateT s m a -> StateT s m a
liftMrgIte SymBool -> a -> a -> a
m = MergingStrategy a
-> SymBool -> StateT s m a -> StateT s m a -> StateT s m a
forall a.
MergingStrategy a
-> SymBool -> StateT s m a -> StateT s m a -> StateT s m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy ((SymBool -> a -> a -> a) -> MergingStrategy a
forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance
  (Mergeable s, SymBranching m) =>
  SymBranching (StateStrict.StateT s m)
  where
  mrgIfWithStrategy :: forall a.
MergingStrategy a
-> SymBool -> StateT s m a -> StateT s m a -> StateT s m a
mrgIfWithStrategy MergingStrategy a
s SymBool
cond (StateStrict.StateT s -> m (a, s)
t) (StateStrict.StateT s -> m (a, s)
f) =
    (s -> m (a, s)) -> StateT s m a
forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateStrict.StateT ((s -> m (a, s)) -> StateT s m a)
-> (s -> m (a, s)) -> StateT s m a
forall a b. (a -> b) -> a -> b
$
      \s
v ->
        MergingStrategy (a, s)
-> SymBool -> m (a, s) -> m (a, s) -> m (a, s)
forall a. MergingStrategy a -> SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (MergingStrategy a -> MergingStrategy s -> MergingStrategy (a, s)
forall a b.
MergingStrategy a -> MergingStrategy b -> MergingStrategy (a, b)
forall (u :: * -> * -> *) a b.
Mergeable2 u =>
MergingStrategy a -> MergingStrategy b -> MergingStrategy (u a b)
liftRootStrategy2 MergingStrategy a
s MergingStrategy s
forall a. Mergeable a => MergingStrategy a
rootStrategy) SymBool
cond (s -> m (a, s)
t s
v) (s -> m (a, s)
f s
v)
  {-# INLINE mrgIfWithStrategy #-}
  mrgIfPropagatedStrategy :: forall a. SymBool -> StateT s m a -> StateT s m a -> StateT s m a
mrgIfPropagatedStrategy SymBool
cond (StateStrict.StateT s -> m (a, s)
t) (StateStrict.StateT s -> m (a, s)
f) =
    (s -> m (a, s)) -> StateT s m a
forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateStrict.StateT ((s -> m (a, s)) -> StateT s m a)
-> (s -> m (a, s)) -> StateT s m a
forall a b. (a -> b) -> a -> b
$ \s
v -> SymBool -> m (a, s) -> m (a, s) -> m (a, s)
forall a. SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
SymBool -> u a -> u a -> u a
mrgIfPropagatedStrategy SymBool
cond (s -> m (a, s)
t s
v) (s -> m (a, s)
f s
v)
  {-# INLINE mrgIfPropagatedStrategy #-}

-- WriterT
instance
  (Mergeable s, Mergeable a, SymBranching m, Monoid s) =>
  SimpleMergeable (WriterLazy.WriterT s m a)
  where
  mrgIte :: SymBool -> WriterT s m a -> WriterT s m a -> WriterT s m a
mrgIte = SymBool -> WriterT s m a -> WriterT s m a -> WriterT s m a
forall (u :: * -> *) a.
(SymBranching u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
  {-# INLINE mrgIte #-}

instance
  (Mergeable s, SymBranching m, Monoid s) =>
  SimpleMergeable1 (WriterLazy.WriterT s m)
  where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a)
-> SymBool -> WriterT s m a -> WriterT s m a -> WriterT s m a
liftMrgIte SymBool -> a -> a -> a
m = MergingStrategy a
-> SymBool -> WriterT s m a -> WriterT s m a -> WriterT s m a
forall a.
MergingStrategy a
-> SymBool -> WriterT s m a -> WriterT s m a -> WriterT s m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy ((SymBool -> a -> a -> a) -> MergingStrategy a
forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance
  (Mergeable s, SymBranching m, Monoid s) =>
  SymBranching (WriterLazy.WriterT s m)
  where
  mrgIfWithStrategy :: forall a.
MergingStrategy a
-> SymBool -> WriterT s m a -> WriterT s m a -> WriterT s m a
mrgIfWithStrategy MergingStrategy a
s SymBool
cond (WriterLazy.WriterT m (a, s)
t) (WriterLazy.WriterT m (a, s)
f) =
    m (a, s) -> WriterT s m a
forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
WriterLazy.WriterT (m (a, s) -> WriterT s m a) -> m (a, s) -> WriterT s m a
forall a b. (a -> b) -> a -> b
$
      MergingStrategy (a, s)
-> SymBool -> m (a, s) -> m (a, s) -> m (a, s)
forall a. MergingStrategy a -> SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (MergingStrategy a -> MergingStrategy s -> MergingStrategy (a, s)
forall a b.
MergingStrategy a -> MergingStrategy b -> MergingStrategy (a, b)
forall (u :: * -> * -> *) a b.
Mergeable2 u =>
MergingStrategy a -> MergingStrategy b -> MergingStrategy (u a b)
liftRootStrategy2 MergingStrategy a
s MergingStrategy s
forall a. Mergeable a => MergingStrategy a
rootStrategy) SymBool
cond m (a, s)
t m (a, s)
f
  {-# INLINE mrgIfWithStrategy #-}
  mrgIfPropagatedStrategy :: forall a.
SymBool -> WriterT s m a -> WriterT s m a -> WriterT s m a
mrgIfPropagatedStrategy SymBool
cond (WriterLazy.WriterT m (a, s)
t) (WriterLazy.WriterT m (a, s)
f) =
    m (a, s) -> WriterT s m a
forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
WriterLazy.WriterT (m (a, s) -> WriterT s m a) -> m (a, s) -> WriterT s m a
forall a b. (a -> b) -> a -> b
$ SymBool -> m (a, s) -> m (a, s) -> m (a, s)
forall a. SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
SymBool -> u a -> u a -> u a
mrgIfPropagatedStrategy SymBool
cond m (a, s)
t m (a, s)
f
  {-# INLINE mrgIfPropagatedStrategy #-}

instance
  (Mergeable s, Mergeable a, SymBranching m, Monoid s) =>
  SimpleMergeable (WriterStrict.WriterT s m a)
  where
  mrgIte :: SymBool -> WriterT s m a -> WriterT s m a -> WriterT s m a
mrgIte = SymBool -> WriterT s m a -> WriterT s m a -> WriterT s m a
forall (u :: * -> *) a.
(SymBranching u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
  {-# INLINE mrgIte #-}

instance
  (Mergeable s, SymBranching m, Monoid s) =>
  SimpleMergeable1 (WriterStrict.WriterT s m)
  where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a)
-> SymBool -> WriterT s m a -> WriterT s m a -> WriterT s m a
liftMrgIte SymBool -> a -> a -> a
m = MergingStrategy a
-> SymBool -> WriterT s m a -> WriterT s m a -> WriterT s m a
forall a.
MergingStrategy a
-> SymBool -> WriterT s m a -> WriterT s m a -> WriterT s m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy ((SymBool -> a -> a -> a) -> MergingStrategy a
forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance
  (Mergeable s, SymBranching m, Monoid s) =>
  SymBranching (WriterStrict.WriterT s m)
  where
  mrgIfWithStrategy :: forall a.
MergingStrategy a
-> SymBool -> WriterT s m a -> WriterT s m a -> WriterT s m a
mrgIfWithStrategy MergingStrategy a
s SymBool
cond (WriterStrict.WriterT m (a, s)
t) (WriterStrict.WriterT m (a, s)
f) =
    m (a, s) -> WriterT s m a
forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
WriterStrict.WriterT (m (a, s) -> WriterT s m a) -> m (a, s) -> WriterT s m a
forall a b. (a -> b) -> a -> b
$
      MergingStrategy (a, s)
-> SymBool -> m (a, s) -> m (a, s) -> m (a, s)
forall a. MergingStrategy a -> SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (MergingStrategy a -> MergingStrategy s -> MergingStrategy (a, s)
forall a b.
MergingStrategy a -> MergingStrategy b -> MergingStrategy (a, b)
forall (u :: * -> * -> *) a b.
Mergeable2 u =>
MergingStrategy a -> MergingStrategy b -> MergingStrategy (u a b)
liftRootStrategy2 MergingStrategy a
s MergingStrategy s
forall a. Mergeable a => MergingStrategy a
rootStrategy) SymBool
cond m (a, s)
t m (a, s)
f
  {-# INLINE mrgIfWithStrategy #-}
  mrgIfPropagatedStrategy :: forall a.
SymBool -> WriterT s m a -> WriterT s m a -> WriterT s m a
mrgIfPropagatedStrategy
    SymBool
cond
    (WriterStrict.WriterT m (a, s)
t)
    (WriterStrict.WriterT m (a, s)
f) =
      m (a, s) -> WriterT s m a
forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
WriterStrict.WriterT (m (a, s) -> WriterT s m a) -> m (a, s) -> WriterT s m a
forall a b. (a -> b) -> a -> b
$ SymBool -> m (a, s) -> m (a, s) -> m (a, s)
forall a. SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
SymBool -> u a -> u a -> u a
mrgIfPropagatedStrategy SymBool
cond m (a, s)
t m (a, s)
f
  {-# INLINE mrgIfPropagatedStrategy #-}

-- ReaderT
instance
  (Mergeable a, SymBranching m) =>
  SimpleMergeable (ReaderT s m a)
  where
  mrgIte :: SymBool -> ReaderT s m a -> ReaderT s m a -> ReaderT s m a
mrgIte = SymBool -> ReaderT s m a -> ReaderT s m a -> ReaderT s m a
forall (u :: * -> *) a.
(SymBranching u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
  {-# INLINE mrgIte #-}

instance
  (SymBranching m) =>
  SimpleMergeable1 (ReaderT s m)
  where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a)
-> SymBool -> ReaderT s m a -> ReaderT s m a -> ReaderT s m a
liftMrgIte SymBool -> a -> a -> a
m = MergingStrategy a
-> SymBool -> ReaderT s m a -> ReaderT s m a -> ReaderT s m a
forall a.
MergingStrategy a
-> SymBool -> ReaderT s m a -> ReaderT s m a -> ReaderT s m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy ((SymBool -> a -> a -> a) -> MergingStrategy a
forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance
  (SymBranching m) =>
  SymBranching (ReaderT s m)
  where
  mrgIfWithStrategy :: forall a.
MergingStrategy a
-> SymBool -> ReaderT s m a -> ReaderT s m a -> ReaderT s m a
mrgIfWithStrategy MergingStrategy a
s SymBool
cond (ReaderT s -> m a
t) (ReaderT s -> m a
f) =
    (s -> m a) -> ReaderT s m a
forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT ((s -> m a) -> ReaderT s m a) -> (s -> m a) -> ReaderT s m a
forall a b. (a -> b) -> a -> b
$ \s
v -> MergingStrategy a -> SymBool -> m a -> m a -> m a
forall a. MergingStrategy a -> SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy MergingStrategy a
s SymBool
cond (s -> m a
t s
v) (s -> m a
f s
v)
  {-# INLINE mrgIfWithStrategy #-}
  mrgIfPropagatedStrategy :: forall a.
SymBool -> ReaderT s m a -> ReaderT s m a -> ReaderT s m a
mrgIfPropagatedStrategy SymBool
cond (ReaderT s -> m a
t) (ReaderT s -> m a
f) =
    (s -> m a) -> ReaderT s m a
forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT ((s -> m a) -> ReaderT s m a) -> (s -> m a) -> ReaderT s m a
forall a b. (a -> b) -> a -> b
$ \s
v -> SymBool -> m a -> m a -> m a
forall a. SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
SymBool -> u a -> u a -> u a
mrgIfPropagatedStrategy SymBool
cond (s -> m a
t s
v) (s -> m a
f s
v)
  {-# INLINE mrgIfPropagatedStrategy #-}

-- IdentityT
instance
  (SymBranching m, Mergeable a) =>
  SimpleMergeable (IdentityT m a)
  where
  mrgIte :: SymBool -> IdentityT m a -> IdentityT m a -> IdentityT m a
mrgIte = SymBool -> IdentityT m a -> IdentityT m a -> IdentityT m a
forall (u :: * -> *) a.
(SymBranching u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
  {-# INLINE mrgIte #-}

instance (SymBranching m) => SimpleMergeable1 (IdentityT m) where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a)
-> SymBool -> IdentityT m a -> IdentityT m a -> IdentityT m a
liftMrgIte SymBool -> a -> a -> a
m = MergingStrategy a
-> SymBool -> IdentityT m a -> IdentityT m a -> IdentityT m a
forall a.
MergingStrategy a
-> SymBool -> IdentityT m a -> IdentityT m a -> IdentityT m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy ((SymBool -> a -> a -> a) -> MergingStrategy a
forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance (SymBranching m) => SymBranching (IdentityT m) where
  mrgIfWithStrategy :: forall a.
MergingStrategy a
-> SymBool -> IdentityT m a -> IdentityT m a -> IdentityT m a
mrgIfWithStrategy MergingStrategy a
s SymBool
cond (IdentityT m a
l) (IdentityT m a
r) =
    m a -> IdentityT m a
forall {k} (f :: k -> *) (a :: k). f a -> IdentityT f a
IdentityT (m a -> IdentityT m a) -> m a -> IdentityT m a
forall a b. (a -> b) -> a -> b
$ MergingStrategy a -> SymBool -> m a -> m a -> m a
forall a. MergingStrategy a -> SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy MergingStrategy a
s SymBool
cond m a
l m a
r
  {-# INLINE mrgIfWithStrategy #-}
  mrgIfPropagatedStrategy :: forall a.
SymBool -> IdentityT m a -> IdentityT m a -> IdentityT m a
mrgIfPropagatedStrategy SymBool
cond (IdentityT m a
l) (IdentityT m a
r) =
    m a -> IdentityT m a
forall {k} (f :: k -> *) (a :: k). f a -> IdentityT f a
IdentityT (m a -> IdentityT m a) -> m a -> IdentityT m a
forall a b. (a -> b) -> a -> b
$ SymBool -> m a -> m a -> m a
forall a. SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
SymBool -> u a -> u a -> u a
mrgIfPropagatedStrategy SymBool
cond m a
l m a
r
  {-# INLINE mrgIfPropagatedStrategy #-}

-- ContT
instance (SymBranching m, Mergeable r) => SimpleMergeable (ContT r m a) where
  mrgIte :: SymBool -> ContT r m a -> ContT r m a -> ContT r m a
mrgIte SymBool
cond (ContT (a -> m r) -> m r
l) (ContT (a -> m r) -> m r
r) = ((a -> m r) -> m r) -> ContT r m a
forall {k} (r :: k) (m :: k -> *) a.
((a -> m r) -> m r) -> ContT r m a
ContT (((a -> m r) -> m r) -> ContT r m a)
-> ((a -> m r) -> m r) -> ContT r m a
forall a b. (a -> b) -> a -> b
$ \a -> m r
c -> SymBool -> m r -> m r -> m r
forall (u :: * -> *) a.
(SymBranching u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf SymBool
cond ((a -> m r) -> m r
l a -> m r
c) ((a -> m r) -> m r
r a -> m r
c)
  {-# INLINE mrgIte #-}

instance (SymBranching m, Mergeable r) => SimpleMergeable1 (ContT r m) where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a)
-> SymBool -> ContT r m a -> ContT r m a -> ContT r m a
liftMrgIte SymBool -> a -> a -> a
m = MergingStrategy a
-> SymBool -> ContT r m a -> ContT r m a -> ContT r m a
forall a.
MergingStrategy a
-> SymBool -> ContT r m a -> ContT r m a -> ContT r m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy ((SymBool -> a -> a -> a) -> MergingStrategy a
forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance (SymBranching m, Mergeable r) => SymBranching (ContT r m) where
  mrgIfWithStrategy :: forall a.
MergingStrategy a
-> SymBool -> ContT r m a -> ContT r m a -> ContT r m a
mrgIfWithStrategy MergingStrategy a
_ SymBool
cond (ContT (a -> m r) -> m r
l) (ContT (a -> m r) -> m r
r) =
    ((a -> m r) -> m r) -> ContT r m a
forall {k} (r :: k) (m :: k -> *) a.
((a -> m r) -> m r) -> ContT r m a
ContT (((a -> m r) -> m r) -> ContT r m a)
-> ((a -> m r) -> m r) -> ContT r m a
forall a b. (a -> b) -> a -> b
$ \a -> m r
c -> SymBool -> m r -> m r -> m r
forall (u :: * -> *) a.
(SymBranching u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf SymBool
cond ((a -> m r) -> m r
l a -> m r
c) ((a -> m r) -> m r
r a -> m r
c)
  {-# INLINE mrgIfWithStrategy #-}
  mrgIfPropagatedStrategy :: forall a. SymBool -> ContT r m a -> ContT r m a -> ContT r m a
mrgIfPropagatedStrategy SymBool
cond (ContT (a -> m r) -> m r
l) (ContT (a -> m r) -> m r
r) =
    ((a -> m r) -> m r) -> ContT r m a
forall {k} (r :: k) (m :: k -> *) a.
((a -> m r) -> m r) -> ContT r m a
ContT (((a -> m r) -> m r) -> ContT r m a)
-> ((a -> m r) -> m r) -> ContT r m a
forall a b. (a -> b) -> a -> b
$ \a -> m r
c -> SymBool -> m r -> m r -> m r
forall a. SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
SymBool -> u a -> u a -> u a
mrgIfPropagatedStrategy SymBool
cond ((a -> m r) -> m r
l a -> m r
c) ((a -> m r) -> m r
r a -> m r
c)
  {-# INLINE mrgIfPropagatedStrategy #-}

-- RWST
instance
  (Mergeable s, Mergeable w, Monoid w, Mergeable a, SymBranching m) =>
  SimpleMergeable (RWSLazy.RWST r w s m a)
  where
  mrgIte :: SymBool -> RWST r w s m a -> RWST r w s m a -> RWST r w s m a
mrgIte = SymBool -> RWST r w s m a -> RWST r w s m a -> RWST r w s m a
forall (u :: * -> *) a.
(SymBranching u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
  {-# INLINE mrgIte #-}

instance
  (Mergeable s, Mergeable w, Monoid w, SymBranching m) =>
  SimpleMergeable1 (RWSLazy.RWST r w s m)
  where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a)
-> SymBool -> RWST r w s m a -> RWST r w s m a -> RWST r w s m a
liftMrgIte SymBool -> a -> a -> a
m = MergingStrategy a
-> SymBool -> RWST r w s m a -> RWST r w s m a -> RWST r w s m a
forall a.
MergingStrategy a
-> SymBool -> RWST r w s m a -> RWST r w s m a -> RWST r w s m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy ((SymBool -> a -> a -> a) -> MergingStrategy a
forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance
  (Mergeable s, Mergeable w, Monoid w, SymBranching m) =>
  SymBranching (RWSLazy.RWST r w s m)
  where
  mrgIfWithStrategy :: forall a.
MergingStrategy a
-> SymBool -> RWST r w s m a -> RWST r w s m a -> RWST r w s m a
mrgIfWithStrategy MergingStrategy a
ms SymBool
cond (RWSLazy.RWST r -> s -> m (a, s, w)
t) (RWSLazy.RWST r -> s -> m (a, s, w)
f) =
    (r -> s -> m (a, s, w)) -> RWST r w s m a
forall r w s (m :: * -> *) a.
(r -> s -> m (a, s, w)) -> RWST r w s m a
RWSLazy.RWST ((r -> s -> m (a, s, w)) -> RWST r w s m a)
-> (r -> s -> m (a, s, w)) -> RWST r w s m a
forall a b. (a -> b) -> a -> b
$ \r
r s
s ->
      MergingStrategy (a, s, w)
-> SymBool -> m (a, s, w) -> m (a, s, w) -> m (a, s, w)
forall a. MergingStrategy a -> SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy
        (MergingStrategy a
-> MergingStrategy s
-> MergingStrategy w
-> MergingStrategy (a, s, w)
forall a b c.
MergingStrategy a
-> MergingStrategy b
-> MergingStrategy c
-> MergingStrategy (a, b, c)
forall (u :: * -> * -> * -> *) a b c.
Mergeable3 u =>
MergingStrategy a
-> MergingStrategy b
-> MergingStrategy c
-> MergingStrategy (u a b c)
liftRootStrategy3 MergingStrategy a
ms MergingStrategy s
forall a. Mergeable a => MergingStrategy a
rootStrategy MergingStrategy w
forall a. Mergeable a => MergingStrategy a
rootStrategy)
        SymBool
cond
        (r -> s -> m (a, s, w)
t r
r s
s)
        (r -> s -> m (a, s, w)
f r
r s
s)
  {-# INLINE mrgIfWithStrategy #-}
  mrgIfPropagatedStrategy :: forall a.
SymBool -> RWST r w s m a -> RWST r w s m a -> RWST r w s m a
mrgIfPropagatedStrategy SymBool
cond (RWSLazy.RWST r -> s -> m (a, s, w)
t) (RWSLazy.RWST r -> s -> m (a, s, w)
f) =
    (r -> s -> m (a, s, w)) -> RWST r w s m a
forall r w s (m :: * -> *) a.
(r -> s -> m (a, s, w)) -> RWST r w s m a
RWSLazy.RWST ((r -> s -> m (a, s, w)) -> RWST r w s m a)
-> (r -> s -> m (a, s, w)) -> RWST r w s m a
forall a b. (a -> b) -> a -> b
$ \r
r s
s -> SymBool -> m (a, s, w) -> m (a, s, w) -> m (a, s, w)
forall a. SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
SymBool -> u a -> u a -> u a
mrgIfPropagatedStrategy SymBool
cond (r -> s -> m (a, s, w)
t r
r s
s) (r -> s -> m (a, s, w)
f r
r s
s)
  {-# INLINE mrgIfPropagatedStrategy #-}

instance
  (Mergeable s, Mergeable w, Monoid w, Mergeable a, SymBranching m) =>
  SimpleMergeable (RWSStrict.RWST r w s m a)
  where
  mrgIte :: SymBool -> RWST r w s m a -> RWST r w s m a -> RWST r w s m a
mrgIte = SymBool -> RWST r w s m a -> RWST r w s m a -> RWST r w s m a
forall (u :: * -> *) a.
(SymBranching u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
  {-# INLINE mrgIte #-}

instance
  (Mergeable s, Mergeable w, Monoid w, SymBranching m) =>
  SimpleMergeable1 (RWSStrict.RWST r w s m)
  where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a)
-> SymBool -> RWST r w s m a -> RWST r w s m a -> RWST r w s m a
liftMrgIte SymBool -> a -> a -> a
m = MergingStrategy a
-> SymBool -> RWST r w s m a -> RWST r w s m a -> RWST r w s m a
forall a.
MergingStrategy a
-> SymBool -> RWST r w s m a -> RWST r w s m a -> RWST r w s m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy ((SymBool -> a -> a -> a) -> MergingStrategy a
forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance
  (Mergeable s, Mergeable w, Monoid w, SymBranching m) =>
  SymBranching (RWSStrict.RWST r w s m)
  where
  mrgIfWithStrategy :: forall a.
MergingStrategy a
-> SymBool -> RWST r w s m a -> RWST r w s m a -> RWST r w s m a
mrgIfWithStrategy MergingStrategy a
ms SymBool
cond (RWSStrict.RWST r -> s -> m (a, s, w)
t) (RWSStrict.RWST r -> s -> m (a, s, w)
f) =
    (r -> s -> m (a, s, w)) -> RWST r w s m a
forall r w s (m :: * -> *) a.
(r -> s -> m (a, s, w)) -> RWST r w s m a
RWSStrict.RWST ((r -> s -> m (a, s, w)) -> RWST r w s m a)
-> (r -> s -> m (a, s, w)) -> RWST r w s m a
forall a b. (a -> b) -> a -> b
$ \r
r s
s ->
      MergingStrategy (a, s, w)
-> SymBool -> m (a, s, w) -> m (a, s, w) -> m (a, s, w)
forall a. MergingStrategy a -> SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy
        (MergingStrategy a
-> MergingStrategy s
-> MergingStrategy w
-> MergingStrategy (a, s, w)
forall a b c.
MergingStrategy a
-> MergingStrategy b
-> MergingStrategy c
-> MergingStrategy (a, b, c)
forall (u :: * -> * -> * -> *) a b c.
Mergeable3 u =>
MergingStrategy a
-> MergingStrategy b
-> MergingStrategy c
-> MergingStrategy (u a b c)
liftRootStrategy3 MergingStrategy a
ms MergingStrategy s
forall a. Mergeable a => MergingStrategy a
rootStrategy MergingStrategy w
forall a. Mergeable a => MergingStrategy a
rootStrategy)
        SymBool
cond
        (r -> s -> m (a, s, w)
t r
r s
s)
        (r -> s -> m (a, s, w)
f r
r s
s)
  {-# INLINE mrgIfWithStrategy #-}
  mrgIfPropagatedStrategy :: forall a.
SymBool -> RWST r w s m a -> RWST r w s m a -> RWST r w s m a
mrgIfPropagatedStrategy SymBool
cond (RWSStrict.RWST r -> s -> m (a, s, w)
t) (RWSStrict.RWST r -> s -> m (a, s, w)
f) =
    (r -> s -> m (a, s, w)) -> RWST r w s m a
forall r w s (m :: * -> *) a.
(r -> s -> m (a, s, w)) -> RWST r w s m a
RWSStrict.RWST ((r -> s -> m (a, s, w)) -> RWST r w s m a)
-> (r -> s -> m (a, s, w)) -> RWST r w s m a
forall a b. (a -> b) -> a -> b
$ \r
r s
s -> SymBool -> m (a, s, w) -> m (a, s, w) -> m (a, s, w)
forall a. SymBool -> m a -> m a -> m a
forall (u :: * -> *) a.
SymBranching u =>
SymBool -> u a -> u a -> u a
mrgIfPropagatedStrategy SymBool
cond (r -> s -> m (a, s, w)
t r
r s
s) (r -> s -> m (a, s, w)
f r
r s
s)
  {-# INLINE mrgIfPropagatedStrategy #-}

-- Product
deriving via
  (Default (Product l r a))
  instance
    (SimpleMergeable (l a), SimpleMergeable (r a)) =>
    SimpleMergeable (Product l r a)

deriving via
  (Default1 (Product l r))
  instance
    (SimpleMergeable1 l, SimpleMergeable1 r) => SimpleMergeable1 (Product l r)

-- Compose
deriving via
  (Default (Compose f g a))
  instance
    (SimpleMergeable (f (g a))) =>
    SimpleMergeable (Compose f g a)

instance
  (SimpleMergeable1 f, SimpleMergeable1 g) =>
  SimpleMergeable1 (Compose f g)
  where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a)
-> SymBool -> Compose f g a -> Compose f g a -> Compose f g a
liftMrgIte SymBool -> a -> a -> a
m SymBool
cond (Compose f (g a)
l) (Compose f (g a)
r) =
    f (g a) -> Compose f g a
forall {k} {k1} (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose (f (g a) -> Compose f g a) -> f (g a) -> Compose f g a
forall a b. (a -> b) -> a -> b
$ (SymBool -> g a -> g a -> g a)
-> SymBool -> f (g a) -> f (g a) -> f (g a)
forall a. (SymBool -> a -> a -> a) -> SymBool -> f a -> f a -> f a
forall (u :: * -> *) a.
SimpleMergeable1 u =>
(SymBool -> a -> a -> a) -> SymBool -> u a -> u a -> u a
liftMrgIte ((SymBool -> a -> a -> a) -> SymBool -> g a -> g a -> g a
forall a. (SymBool -> a -> a -> a) -> SymBool -> g a -> g a -> g a
forall (u :: * -> *) a.
SimpleMergeable1 u =>
(SymBool -> a -> a -> a) -> SymBool -> u a -> u a -> u a
liftMrgIte SymBool -> a -> a -> a
m) SymBool
cond f (g a)
l f (g a)
r

-- Const
deriving via
  (Default (Const a b))
  instance
    (SimpleMergeable a) => SimpleMergeable (Const a b)

deriving via
  (Default1 (Const a))
  instance
    (SimpleMergeable a) => SimpleMergeable1 (Const a)

-- Alt
deriving via
  (Default (Alt f a))
  instance
    (SimpleMergeable (f a)) => SimpleMergeable (Alt f a)

deriving via
  (Default1 (Alt f))
  instance
    (SimpleMergeable1 f) => SimpleMergeable1 (Alt f)

-- Ap
deriving via
  (Default (Ap f a))
  instance
    (SimpleMergeable (f a)) => SimpleMergeable (Ap f a)

deriving via
  (Default1 (Ap f))
  instance
    (SimpleMergeable1 f) => SimpleMergeable1 (Ap f)

-- Endo
instance (SimpleMergeable a) => SimpleMergeable (Endo a) where
  mrgIte :: SymBool -> Endo a -> Endo a -> Endo a
mrgIte = SymBool -> Endo a -> Endo a -> Endo a
forall (u :: * -> *) a.
(SimpleMergeable1 u, SimpleMergeable a) =>
SymBool -> u a -> u a -> u a
mrgIte1
  {-# INLINE mrgIte #-}

instance SimpleMergeable1 Endo where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a) -> SymBool -> Endo a -> Endo a -> Endo a
liftMrgIte SymBool -> a -> a -> a
m SymBool
cond (Endo a -> a
l) (Endo a -> a
r) = (a -> a) -> Endo a
forall a. (a -> a) -> Endo a
Endo ((a -> a) -> Endo a) -> (a -> a) -> Endo a
forall a b. (a -> b) -> a -> b
$ (SymBool -> a -> a -> a)
-> SymBool -> (a -> a) -> (a -> a) -> a -> a
forall a.
(SymBool -> a -> a -> a)
-> SymBool -> (a -> a) -> (a -> a) -> a -> a
forall (u :: * -> *) a.
SimpleMergeable1 u =>
(SymBool -> a -> a -> a) -> SymBool -> u a -> u a -> u a
liftMrgIte SymBool -> a -> a -> a
m SymBool
cond a -> a
l a -> a
r
  {-# INLINE liftMrgIte #-}

-- Generic
deriving via (Default (U1 p)) instance SimpleMergeable (U1 p)

deriving via (Default (V1 p)) instance SimpleMergeable (V1 p)

deriving via
  (Default (K1 i c p))
  instance
    (SimpleMergeable c) => SimpleMergeable (K1 i c p)

deriving via
  (Default (M1 i c f p))
  instance
    (SimpleMergeable (f p)) => SimpleMergeable (M1 i c f p)

deriving via
  (Default ((f :*: g) p))
  instance
    (SimpleMergeable (f p), SimpleMergeable (g p)) =>
    SimpleMergeable ((f :*: g) p)

deriving via
  (Default (Par1 p))
  instance
    (SimpleMergeable p) => SimpleMergeable (Par1 p)

deriving via
  (Default (Rec1 f p))
  instance
    (SimpleMergeable (f p)) => SimpleMergeable (Rec1 f p)

deriving via
  (Default ((f :.: g) p))
  instance
    (SimpleMergeable (f (g p))) => SimpleMergeable ((f :.: g) p)

#define SIMPLE_MERGEABLE_SIMPLE(symtype) \
instance SimpleMergeable symtype where \
  mrgIte = symIte; \
  {-# INLINE mrgIte #-}

#define SIMPLE_MERGEABLE_BV(symtype) \
instance (KnownNat n, 1 <= n) => SimpleMergeable (symtype n) where \
  mrgIte = symIte; \
  {-# INLINE mrgIte #-}

#define SIMPLE_MERGEABLE_FUN(cop, op) \
instance (SupportedPrim (cop ca cb), LinkedRep ca sa, LinkedRep cb sb) => \
  SimpleMergeable (op sa sb) where \
  mrgIte = symIte; \
  {-# INLINE mrgIte #-}

#if 1
SIMPLE_MERGEABLE_SIMPLE(SymBool)
SIMPLE_MERGEABLE_SIMPLE(SymInteger)
SIMPLE_MERGEABLE_SIMPLE(SymFPRoundingMode)
SIMPLE_MERGEABLE_BV(SymIntN)
SIMPLE_MERGEABLE_BV(SymWordN)
SIMPLE_MERGEABLE_FUN((=->), (=~>))
SIMPLE_MERGEABLE_FUN((-->), (-~>))
#endif

instance (ValidFP eb sb) => SimpleMergeable (SymFP eb sb) where
  mrgIte :: SymBool -> SymFP eb sb -> SymFP eb sb -> SymFP eb sb
mrgIte = SymBool -> SymFP eb sb -> SymFP eb sb -> SymFP eb sb
forall v. ITEOp v => SymBool -> v -> v -> v
symIte
  {-# INLINE mrgIte #-}