{-# LANGUAGE CPP #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ViewPatterns #-}

-- |
-- Module      :   Grisette.Core.Data.Class.SimpleMergeable
-- 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.SimpleMergeable
  ( -- * Simple mergeable types
    SimpleMergeable (..),
    SimpleMergeable1 (..),
    mrgIte1,
    SimpleMergeable2 (..),
    mrgIte2,

    -- * UnionLike operations
    UnionLike (..),
    mrgIf,
    merge,
    mrgSingle,
    UnionPrjOp (..),
    pattern SingleU,
    pattern IfU,
    simpleMerge,
    onUnion,
    onUnion2,
    onUnion3,
    onUnion4,
    (#~),
  )
where

import Control.Monad.Except
import Control.Monad.Identity
import qualified Control.Monad.RWS.Lazy as RWSLazy
import qualified Control.Monad.RWS.Strict as RWSStrict
import Control.Monad.Reader
import qualified Control.Monad.State.Lazy as StateLazy
import qualified Control.Monad.State.Strict as StateStrict
import Control.Monad.Trans.Cont
import Control.Monad.Trans.Maybe
import qualified Control.Monad.Writer.Lazy as WriterLazy
import qualified Control.Monad.Writer.Strict as WriterStrict
import Data.Kind
import GHC.Generics
import GHC.TypeNats
import Generics.Deriving
import Grisette.Core.Data.Class.Bool
import Grisette.Core.Data.Class.Function
import Grisette.Core.Data.Class.Mergeable
import Grisette.IR.SymPrim.Data.Prim.InternedTerm.Term
import {-# SOURCE #-} Grisette.IR.SymPrim.Data.SymPrim

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

-- | Auxiliary class for the generic derivation for the 'SimpleMergeable' class.
class SimpleMergeable' f where
  mrgIte' :: SymBool -> f a -> f a -> f a

instance (SimpleMergeable' U1) where
  mrgIte' :: forall a. SymBool -> U1 a -> U1 a -> U1 a
mrgIte' SymBool
_ U1 a
t U1 a
_ = U1 a
t
  {-# INLINE mrgIte' #-}

instance (SimpleMergeable' V1) where
  mrgIte' :: forall a. SymBool -> V1 a -> V1 a -> V1 a
mrgIte' SymBool
_ V1 a
t V1 a
_ = V1 a
t
  {-# INLINE mrgIte' #-}

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

instance (SimpleMergeable' a) => (SimpleMergeable' (M1 i c a)) where
  mrgIte' :: forall a. SymBool -> M1 i c a a -> M1 i c a a -> M1 i c a a
mrgIte' SymBool
cond (M1 a a
a) (M1 a a
b) = forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a.
SimpleMergeable' f =>
SymBool -> f a -> f a -> f a
mrgIte' SymBool
cond a a
a a a
b
  {-# INLINE mrgIte' #-}

instance (SimpleMergeable' a, SimpleMergeable' b) => (SimpleMergeable' (a :*: b)) where
  mrgIte' :: forall a. SymBool -> (:*:) a b a -> (:*:) a b a -> (:*:) a b a
mrgIte' SymBool
cond (a a
a1 :*: b a
a2) (a a
b1 :*: b a
b2) = forall (f :: * -> *) a.
SimpleMergeable' f =>
SymBool -> f a -> f a -> f a
mrgIte' SymBool
cond a a
a1 a a
b1 forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
:*: forall (f :: * -> *) a.
SimpleMergeable' f =>
SymBool -> f a -> f a -> f a
mrgIte' SymBool
cond b a
a2 b a
b2
  {-# INLINE mrgIte' #-}

-- | 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

instance (Generic a, Mergeable' (Rep a), SimpleMergeable' (Rep a)) => SimpleMergeable (Default a) where
  mrgIte :: SymBool -> Default a -> Default a -> Default a
mrgIte SymBool
cond (Default a
a) (Default a
b) = forall a. a -> Default a
Default forall a b. (a -> b) -> a -> b
$ forall a x. Generic a => Rep a x -> a
to forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a.
SimpleMergeable' f =>
SymBool -> f a -> f a -> f a
mrgIte' SymBool
cond (forall a x. Generic a => a -> Rep a x
from a
a) (forall a x. Generic a => a -> Rep a x
from a
b)
  {-# INLINE mrgIte #-}

-- | Lifting of the 'SimpleMergeable' class to unary type constructors.
class 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 = forall (u :: * -> *) a.
SimpleMergeable1 u =>
(SymBool -> a -> a -> a) -> SymBool -> u a -> u a -> u a
liftMrgIte forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte
{-# INLINE mrgIte1 #-}

-- | Lifting of the 'SimpleMergeable' class to binary type constructors.
class (Mergeable2 u) => 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 = 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 forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte
{-# INLINE mrgIte2 #-}

-- | 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, Mergeable1 u) => UnionLike u where
  -- | Wrap a single value in the union.
  --
  -- Note that this function cannot propagate the 'Mergeable' knowledge.
  --
  -- >>> single "a" :: UnionM SymInteger
  -- <a>
  -- >>> mrgSingle "a" :: UnionM SymInteger
  -- {a}
  single :: a -> u a

  -- | If-then-else on two union values.
  --
  -- Note that this function cannot capture the 'Mergeable' knowledge. However,
  -- it may use the merging strategy from the branches to merge the results.
  --
  -- >>> unionIf "a" (single "b") (single "c") :: UnionM SymInteger
  -- <If a b c>
  -- >>> unionIf "a" (mrgSingle "b") (single "c") :: UnionM SymInteger
  -- {(ite a b c)}
  unionIf :: SymBool -> u a -> u a -> u a

  -- | Merge the contents with some merge strategy.
  --
  -- >>> mergeWithStrategy rootStrategy $ unionIf "a" (single "b") (single "c") :: UnionM 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, 'merge' is usually a better alternative.
  mergeWithStrategy :: MergingStrategy a -> u a -> u a

  -- | Symbolic @if@ control flow with the result merged with some merge strategy.
  --
  -- >>> mrgIfWithStrategy rootStrategy "a" (mrgSingle "b") (single "c") :: UnionM 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
  mrgIfWithStrategy MergingStrategy a
s SymBool
cond u a
l u a
r = forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> u a -> u a
mergeWithStrategy MergingStrategy a
s forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a. UnionLike u => SymBool -> u a -> u a -> u a
unionIf SymBool
cond u a
l u a
r
  {-# INLINE mrgIfWithStrategy #-}

  -- | Wrap a single value in the union and capture the 'Mergeable' knowledge.
  --
  -- >>> mrgSingleWithStrategy rootStrategy "a" :: UnionM SymInteger
  -- {a}
  --
  -- __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, 'mrgSingle' is usually a better alternative.
  mrgSingleWithStrategy :: MergingStrategy a -> a -> u a
  mrgSingleWithStrategy MergingStrategy a
s = forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> u a -> u a
mergeWithStrategy MergingStrategy a
s forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (u :: * -> *) a. UnionLike u => a -> u a
single
  {-# INLINE mrgSingleWithStrategy #-}

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

-- | Merge the contents with the type's root merge strategy.
--
-- Equivalent to @'mergeWithStrategy' 'rootStrategy'@.
--
-- >>> merge $ unionIf "a" (single "b") (single "c") :: UnionM SymInteger
-- {(ite a b c)}
merge :: (UnionLike u, Mergeable a) => u a -> u a
merge :: forall (u :: * -> *) a. (UnionLike u, Mergeable a) => u a -> u a
merge = forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> u a -> u a
mergeWithStrategy forall a. Mergeable a => MergingStrategy a
rootStrategy
{-# INLINE merge #-}

-- | Wrap a single value in the type and propagate the type's root merge strategy.
--
-- Equivalent to @'mrgSingleWithStrategy' 'rootStrategy'@.
--
-- >>> mrgSingle "a" :: UnionM SymInteger
-- {a}
mrgSingle :: (UnionLike u, Mergeable a) => a -> u a
mrgSingle :: forall (u :: * -> *) a. (UnionLike u, Mergeable a) => a -> u a
mrgSingle = forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> a -> u a
mrgSingleWithStrategy forall a. Mergeable a => MergingStrategy a
rootStrategy
{-# INLINE mrgSingle #-}

instance SimpleMergeable () where
  mrgIte :: SymBool -> () -> () -> ()
mrgIte SymBool
_ ()
t ()
_ = ()
t
  {-# INLINE mrgIte #-}

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

instance (SimpleMergeable a) => SimpleMergeable1 ((,) a) where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a) -> SymBool -> (a, a) -> (a, a) -> (a, a)
liftMrgIte SymBool -> a -> a -> a
mb SymBool
cond (a
a1, a
b1) (a
a2, a
b2) = (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)
  {-# 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
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, SimpleMergeable b, SimpleMergeable c) =>
  SimpleMergeable (a, b, c)
  where
  mrgIte :: SymBool -> (a, b, c) -> (a, b, c) -> (a, b, c)
mrgIte SymBool
cond (a
a1, b
b1, c
c1) (a
a2, b
b2, c
c2) = (forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond a
a1 a
a2, forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond b
b1 b
b2, forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond c
c1 c
c2)
  {-# INLINE mrgIte #-}

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

instance
  ( SimpleMergeable a,
    SimpleMergeable b,
    SimpleMergeable c,
    SimpleMergeable d,
    SimpleMergeable e
  ) =>
  SimpleMergeable (a, b, c, d, e)
  where
  mrgIte :: SymBool -> (a, b, c, d, e) -> (a, b, c, d, e) -> (a, b, c, d, e)
mrgIte SymBool
cond (a
a1, b
b1, c
c1, d
d1, e
e1) (a
a2, b
b2, c
c2, d
d2, e
e2) =
    (forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond a
a1 a
a2, forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond b
b1 b
b2, forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond c
c1 c
c2, forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond d
d1 d
d2, forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond e
e1 e
e2)
  {-# INLINE mrgIte #-}

instance
  ( SimpleMergeable a,
    SimpleMergeable b,
    SimpleMergeable c,
    SimpleMergeable d,
    SimpleMergeable e,
    SimpleMergeable f
  ) =>
  SimpleMergeable (a, b, c, d, e, f)
  where
  mrgIte :: SymBool
-> (a, b, c, d, e, f) -> (a, b, c, d, e, f) -> (a, b, c, d, e, f)
mrgIte SymBool
cond (a
a1, b
b1, c
c1, d
d1, e
e1, f
f1) (a
a2, b
b2, c
c2, d
d2, e
e2, f
f2) =
    (forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond a
a1 a
a2, forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond b
b1 b
b2, forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond c
c1 c
c2, forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond d
d1 d
d2, forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond e
e1 e
e2, forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond f
f1 f
f2)
  {-# INLINE mrgIte #-}

instance
  ( SimpleMergeable a,
    SimpleMergeable b,
    SimpleMergeable c,
    SimpleMergeable d,
    SimpleMergeable e,
    SimpleMergeable f,
    SimpleMergeable g
  ) =>
  SimpleMergeable (a, b, c, d, e, f, g)
  where
  mrgIte :: SymBool
-> (a, b, c, d, e, f, g)
-> (a, b, c, d, e, f, g)
-> (a, b, c, d, e, f, g)
mrgIte SymBool
cond (a
a1, b
b1, c
c1, d
d1, e
e1, f
f1, g
g1) (a
a2, b
b2, c
c2, d
d2, e
e2, f
f2, g
g2) =
    ( forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond a
a1 a
a2,
      forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond b
b1 b
b2,
      forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond c
c1 c
c2,
      forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond d
d1 d
d2,
      forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond e
e1 e
e2,
      forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond f
f1 f
f2,
      forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond g
g1 g
g2
    )
  {-# INLINE mrgIte #-}

instance
  ( SimpleMergeable a,
    SimpleMergeable b,
    SimpleMergeable c,
    SimpleMergeable d,
    SimpleMergeable e,
    SimpleMergeable f,
    SimpleMergeable g,
    SimpleMergeable h
  ) =>
  SimpleMergeable (a, b, c, d, e, f, g, h)
  where
  mrgIte :: SymBool
-> (a, b, c, d, e, f, g, h)
-> (a, b, c, d, e, f, g, h)
-> (a, b, c, d, e, f, g, h)
mrgIte SymBool
cond (a
a1, b
b1, c
c1, d
d1, e
e1, f
f1, g
g1, h
h1) (a
a2, b
b2, c
c2, d
d2, e
e2, f
f2, g
g2, h
h2) =
    ( forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond a
a1 a
a2,
      forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond b
b1 b
b2,
      forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond c
c1 c
c2,
      forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond d
d1 d
d2,
      forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond e
e1 e
e2,
      forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond f
f1 f
f2,
      forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond g
g1 g
g2,
      forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond h
h1 h
h2
    )
  {-# INLINE mrgIte #-}

instance SimpleMergeable b => SimpleMergeable (a -> b) where
  mrgIte :: SymBool -> (a -> b) -> (a -> b) -> a -> b
mrgIte = 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 (UnionLike m, Mergeable a) => SimpleMergeable (MaybeT m a) where
  mrgIte :: SymBool -> MaybeT m a -> MaybeT m a -> MaybeT m a
mrgIte = forall (u :: * -> *) a.
(UnionLike u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
  {-# INLINE mrgIte #-}

instance (UnionLike 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 = forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance (UnionLike m) => UnionLike (MaybeT m) where
  mergeWithStrategy :: forall a. MergingStrategy a -> MaybeT m a -> MaybeT m a
mergeWithStrategy MergingStrategy a
s (MaybeT m (Maybe a)
v) = forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> u a -> u a
mergeWithStrategy (forall (u :: * -> *) a.
Mergeable1 u =>
MergingStrategy a -> MergingStrategy (u a)
liftRootStrategy MergingStrategy a
s) m (Maybe a)
v
  {-# INLINE mergeWithStrategy #-}
  mrgIfWithStrategy :: forall a.
MergingStrategy a
-> SymBool -> MaybeT m a -> MaybeT m a -> MaybeT m a
mrgIfWithStrategy MergingStrategy a
s SymBool
cond (MaybeT m (Maybe a)
t) (MaybeT m (Maybe a)
f) = forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall (u :: * -> *) a.
Mergeable1 u =>
MergingStrategy a -> MergingStrategy (u a)
liftRootStrategy MergingStrategy a
s) SymBool
cond m (Maybe a)
t m (Maybe a)
f
  {-# INLINE mrgIfWithStrategy #-}
  single :: forall a. a -> MaybeT m a
single = forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (u :: * -> *) a. UnionLike u => a -> u a
single forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. Monad m => a -> m a
return
  {-# INLINE single #-}
  unionIf :: forall a. SymBool -> MaybeT m a -> MaybeT m a -> MaybeT m a
unionIf SymBool
cond (MaybeT m (Maybe a)
l) (MaybeT m (Maybe a)
r) = forall (m :: * -> *) a. m (Maybe a) -> MaybeT m a
MaybeT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a. UnionLike u => SymBool -> u a -> u a -> u a
unionIf SymBool
cond m (Maybe a)
l m (Maybe a)
r
  {-# INLINE unionIf #-}

instance
  (UnionLike 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 = forall (u :: * -> *) a.
(UnionLike u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
  {-# INLINE mrgIte #-}

instance
  (UnionLike 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 = forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance
  (UnionLike m, Mergeable e) =>
  UnionLike (ExceptT e m)
  where
  mergeWithStrategy :: forall a. MergingStrategy a -> ExceptT e m a -> ExceptT e m a
mergeWithStrategy MergingStrategy a
s (ExceptT m (Either e a)
v) = forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> u a -> u a
mergeWithStrategy (forall (u :: * -> *) a.
Mergeable1 u =>
MergingStrategy a -> MergingStrategy (u a)
liftRootStrategy MergingStrategy a
s) m (Either e a)
v
  {-# INLINE mergeWithStrategy #-}
  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) = forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (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 #-}
  single :: forall a. a -> ExceptT e m a
single = forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (u :: * -> *) a. UnionLike u => a -> u a
single forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *) a. Monad m => a -> m a
return
  {-# INLINE single #-}
  unionIf :: forall a.
SymBool -> ExceptT e m a -> ExceptT e m a -> ExceptT e m a
unionIf SymBool
cond (ExceptT m (Either e a)
l) (ExceptT m (Either e a)
r) = forall e (m :: * -> *) a. m (Either e a) -> ExceptT e m a
ExceptT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a. UnionLike u => SymBool -> u a -> u a -> u a
unionIf SymBool
cond m (Either e a)
l m (Either e a)
r
  {-# INLINE unionIf #-}

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

instance
  (Mergeable s, UnionLike 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 = forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance
  (Mergeable s, UnionLike m) =>
  UnionLike (StateLazy.StateT s m)
  where
  mergeWithStrategy :: forall a. MergingStrategy a -> StateT s m a -> StateT s m a
mergeWithStrategy MergingStrategy a
ms (StateLazy.StateT s -> m (a, s)
f) =
    forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateLazy.StateT forall a b. (a -> b) -> a -> b
$ \s
v -> forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> u a -> u a
mergeWithStrategy (forall (u :: * -> * -> *) a b.
Mergeable2 u =>
MergingStrategy a -> MergingStrategy b -> MergingStrategy (u a b)
liftRootStrategy2 MergingStrategy a
ms forall a. Mergeable a => MergingStrategy a
rootStrategy) forall a b. (a -> b) -> a -> b
$ s -> m (a, s)
f s
v
  {-# INLINE mergeWithStrategy #-}
  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) =
    forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateLazy.StateT forall a b. (a -> b) -> a -> b
$ \s
v -> forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall (u :: * -> * -> *) a b.
Mergeable2 u =>
MergingStrategy a -> MergingStrategy b -> MergingStrategy (u a b)
liftRootStrategy2 MergingStrategy a
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 #-}
  single :: forall a. a -> StateT s m a
single a
x = forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateLazy.StateT forall a b. (a -> b) -> a -> b
$ \s
s -> forall (u :: * -> *) a. UnionLike u => a -> u a
single (a
x, s
s)
  {-# INLINE single #-}
  unionIf :: forall a. SymBool -> StateT s m a -> StateT s m a -> StateT s m a
unionIf SymBool
cond (StateLazy.StateT s -> m (a, s)
l) (StateLazy.StateT s -> m (a, s)
r) =
    forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateLazy.StateT forall a b. (a -> b) -> a -> b
$ \s
s -> forall (u :: * -> *) a. UnionLike u => SymBool -> u a -> u a -> u a
unionIf SymBool
cond (s -> m (a, s)
l s
s) (s -> m (a, s)
r s
s)
  {-# INLINE unionIf #-}

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

instance
  (Mergeable s, UnionLike 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 = forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance
  (Mergeable s, UnionLike m) =>
  UnionLike (StateStrict.StateT s m)
  where
  mergeWithStrategy :: forall a. MergingStrategy a -> StateT s m a -> StateT s m a
mergeWithStrategy MergingStrategy a
ms (StateStrict.StateT s -> m (a, s)
f) =
    forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateStrict.StateT forall a b. (a -> b) -> a -> b
$ \s
v -> forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> u a -> u a
mergeWithStrategy (forall (u :: * -> * -> *) a b.
Mergeable2 u =>
MergingStrategy a -> MergingStrategy b -> MergingStrategy (u a b)
liftRootStrategy2 MergingStrategy a
ms forall a. Mergeable a => MergingStrategy a
rootStrategy) forall a b. (a -> b) -> a -> b
$ s -> m (a, s)
f s
v
  {-# INLINE mergeWithStrategy #-}
  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) =
    forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateStrict.StateT forall a b. (a -> b) -> a -> b
$ \s
v -> forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall (u :: * -> * -> *) a b.
Mergeable2 u =>
MergingStrategy a -> MergingStrategy b -> MergingStrategy (u a b)
liftRootStrategy2 MergingStrategy a
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 #-}
  single :: forall a. a -> StateT s m a
single a
x = forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateStrict.StateT forall a b. (a -> b) -> a -> b
$ \s
s -> forall (u :: * -> *) a. UnionLike u => a -> u a
single (a
x, s
s)
  {-# INLINE single #-}
  unionIf :: forall a. SymBool -> StateT s m a -> StateT s m a -> StateT s m a
unionIf SymBool
cond (StateStrict.StateT s -> m (a, s)
l) (StateStrict.StateT s -> m (a, s)
r) =
    forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
StateStrict.StateT forall a b. (a -> b) -> a -> b
$ \s
s -> forall (u :: * -> *) a. UnionLike u => SymBool -> u a -> u a -> u a
unionIf SymBool
cond (s -> m (a, s)
l s
s) (s -> m (a, s)
r s
s)
  {-# INLINE unionIf #-}

instance
  (Mergeable s, Mergeable a, UnionLike 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 = forall (u :: * -> *) a.
(UnionLike u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
  {-# INLINE mrgIte #-}

instance
  (Mergeable s, UnionLike 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 = forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance
  (Mergeable s, UnionLike m, Monoid s) =>
  UnionLike (WriterLazy.WriterT s m)
  where
  mergeWithStrategy :: forall a. MergingStrategy a -> WriterT s m a -> WriterT s m a
mergeWithStrategy MergingStrategy a
ms (WriterLazy.WriterT m (a, s)
f) = forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
WriterLazy.WriterT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> u a -> u a
mergeWithStrategy (forall (u :: * -> * -> *) a b.
Mergeable2 u =>
MergingStrategy a -> MergingStrategy b -> MergingStrategy (u a b)
liftRootStrategy2 MergingStrategy a
ms forall a. Mergeable a => MergingStrategy a
rootStrategy) m (a, s)
f
  {-# INLINE mergeWithStrategy #-}
  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) =
    forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
WriterLazy.WriterT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall (u :: * -> * -> *) a b.
Mergeable2 u =>
MergingStrategy a -> MergingStrategy b -> MergingStrategy (u a b)
liftRootStrategy2 MergingStrategy a
s forall a. Mergeable a => MergingStrategy a
rootStrategy) SymBool
cond m (a, s)
t m (a, s)
f
  {-# INLINE mrgIfWithStrategy #-}
  single :: forall a. a -> WriterT s m a
single a
x = forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
WriterLazy.WriterT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a. UnionLike u => a -> u a
single (a
x, forall a. Monoid a => a
mempty)
  {-# INLINE single #-}
  unionIf :: forall a.
SymBool -> WriterT s m a -> WriterT s m a -> WriterT s m a
unionIf SymBool
cond (WriterLazy.WriterT m (a, s)
l) (WriterLazy.WriterT m (a, s)
r) =
    forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
WriterLazy.WriterT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a. UnionLike u => SymBool -> u a -> u a -> u a
unionIf SymBool
cond m (a, s)
l m (a, s)
r
  {-# INLINE unionIf #-}

instance
  (Mergeable s, Mergeable a, UnionLike 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 = forall (u :: * -> *) a.
(UnionLike u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
  {-# INLINE mrgIte #-}

instance
  (Mergeable s, UnionLike 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 = forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance
  (Mergeable s, UnionLike m, Monoid s) =>
  UnionLike (WriterStrict.WriterT s m)
  where
  mergeWithStrategy :: forall a. MergingStrategy a -> WriterT s m a -> WriterT s m a
mergeWithStrategy MergingStrategy a
ms (WriterStrict.WriterT m (a, s)
f) = forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
WriterStrict.WriterT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> u a -> u a
mergeWithStrategy (forall (u :: * -> * -> *) a b.
Mergeable2 u =>
MergingStrategy a -> MergingStrategy b -> MergingStrategy (u a b)
liftRootStrategy2 MergingStrategy a
ms forall a. Mergeable a => MergingStrategy a
rootStrategy) m (a, s)
f
  {-# INLINE mergeWithStrategy #-}
  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) =
    forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
WriterStrict.WriterT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall (u :: * -> * -> *) a b.
Mergeable2 u =>
MergingStrategy a -> MergingStrategy b -> MergingStrategy (u a b)
liftRootStrategy2 MergingStrategy a
s forall a. Mergeable a => MergingStrategy a
rootStrategy) SymBool
cond m (a, s)
t m (a, s)
f
  {-# INLINE mrgIfWithStrategy #-}
  single :: forall a. a -> WriterT s m a
single a
x = forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
WriterStrict.WriterT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a. UnionLike u => a -> u a
single (a
x, forall a. Monoid a => a
mempty)
  {-# INLINE single #-}
  unionIf :: forall a.
SymBool -> WriterT s m a -> WriterT s m a -> WriterT s m a
unionIf SymBool
cond (WriterStrict.WriterT m (a, s)
l) (WriterStrict.WriterT m (a, s)
r) =
    forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
WriterStrict.WriterT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a. UnionLike u => SymBool -> u a -> u a -> u a
unionIf SymBool
cond m (a, s)
l m (a, s)
r
  {-# INLINE unionIf #-}

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

instance
  (UnionLike 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 = forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance
  (UnionLike m) =>
  UnionLike (ReaderT s m)
  where
  mergeWithStrategy :: forall a. MergingStrategy a -> ReaderT s m a -> ReaderT s m a
mergeWithStrategy MergingStrategy a
ms (ReaderT s -> m a
f) = forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT forall a b. (a -> b) -> a -> b
$ \s
v -> forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> u a -> u a
mergeWithStrategy MergingStrategy a
ms forall a b. (a -> b) -> a -> b
$ s -> m a
f s
v
  {-# INLINE mergeWithStrategy #-}
  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) =
    forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT forall a b. (a -> b) -> a -> b
$ \s
v -> forall (u :: * -> *) a.
UnionLike 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 #-}
  single :: forall a. a -> ReaderT s m a
single a
x = forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT forall a b. (a -> b) -> a -> b
$ \s
_ -> forall (u :: * -> *) a. UnionLike u => a -> u a
single a
x
  {-# INLINE single #-}
  unionIf :: forall a.
SymBool -> ReaderT s m a -> ReaderT s m a -> ReaderT s m a
unionIf SymBool
cond (ReaderT s -> m a
l) (ReaderT s -> m a
r) = forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT forall a b. (a -> b) -> a -> b
$ \s
s -> forall (u :: * -> *) a. UnionLike u => SymBool -> u a -> u a -> u a
unionIf SymBool
cond (s -> m a
l s
s) (s -> m a
r s
s)
  {-# INLINE unionIf #-}

instance (SimpleMergeable a) => SimpleMergeable (Identity a) where
  mrgIte :: SymBool -> Identity a -> Identity a -> Identity a
mrgIte SymBool
cond (Identity a
l) (Identity a
r) = forall a. a -> Identity a
Identity forall a b. (a -> b) -> a -> b
$ forall a. SimpleMergeable a => SymBool -> a -> a -> a
mrgIte SymBool
cond a
l a
r
  {-# INLINE mrgIte #-}

instance SimpleMergeable1 Identity where
  liftMrgIte :: forall a.
(SymBool -> a -> a -> a)
-> SymBool -> Identity a -> Identity a -> Identity a
liftMrgIte SymBool -> a -> a -> a
mite SymBool
cond (Identity a
l) (Identity a
r) = forall a. a -> Identity a
Identity forall a b. (a -> b) -> a -> b
$ SymBool -> a -> a -> a
mite SymBool
cond a
l a
r
  {-# INLINE liftMrgIte #-}

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

instance (UnionLike 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 = forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance (UnionLike m) => UnionLike (IdentityT m) where
  mergeWithStrategy :: forall a. MergingStrategy a -> IdentityT m a -> IdentityT m a
mergeWithStrategy MergingStrategy a
ms (IdentityT m a
f) =
    forall {k} (f :: k -> *) (a :: k). f a -> IdentityT f a
IdentityT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> u a -> u a
mergeWithStrategy MergingStrategy a
ms m a
f
  {-# INLINE mergeWithStrategy #-}
  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) = forall {k} (f :: k -> *) (a :: k). f a -> IdentityT f a
IdentityT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy MergingStrategy a
s SymBool
cond m a
l m a
r
  {-# INLINE mrgIfWithStrategy #-}
  single :: forall a. a -> IdentityT m a
single a
x = forall {k} (f :: k -> *) (a :: k). f a -> IdentityT f a
IdentityT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a. UnionLike u => a -> u a
single a
x
  {-# INLINE single #-}
  unionIf :: forall a.
SymBool -> IdentityT m a -> IdentityT m a -> IdentityT m a
unionIf SymBool
cond (IdentityT m a
l) (IdentityT m a
r) = forall {k} (f :: k -> *) (a :: k). f a -> IdentityT f a
IdentityT forall a b. (a -> b) -> a -> b
$ forall (u :: * -> *) a. UnionLike u => SymBool -> u a -> u a -> u a
unionIf SymBool
cond m a
l m a
r
  {-# INLINE unionIf #-}

instance (UnionLike 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) = forall {k} (r :: k) (m :: k -> *) a.
((a -> m r) -> m r) -> ContT r m a
ContT forall a b. (a -> b) -> a -> b
$ \a -> m r
c -> forall (u :: * -> *) a.
(UnionLike 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 (UnionLike 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 = forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance (UnionLike m, Mergeable r) => UnionLike (ContT r m) where
  mergeWithStrategy :: forall a. MergingStrategy a -> ContT r m a -> ContT r m a
mergeWithStrategy MergingStrategy a
_ (ContT (a -> m r) -> m r
f) = forall {k} (r :: k) (m :: k -> *) a.
((a -> m r) -> m r) -> ContT r m a
ContT forall a b. (a -> b) -> a -> b
$ \a -> m r
c -> forall (u :: * -> *) a. (UnionLike u, Mergeable a) => u a -> u a
merge ((a -> m r) -> m r
f a -> m r
c)
  {-# INLINE mergeWithStrategy #-}
  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) = forall {k} (r :: k) (m :: k -> *) a.
((a -> m r) -> m r) -> ContT r m a
ContT forall a b. (a -> b) -> a -> b
$ \a -> m r
c -> forall (u :: * -> *) a.
(UnionLike 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 #-}
  single :: forall a. a -> ContT r m a
single a
x = forall {k} (r :: k) (m :: k -> *) a.
((a -> m r) -> m r) -> ContT r m a
ContT forall a b. (a -> b) -> a -> b
$ \a -> m r
c -> a -> m r
c a
x
  {-# INLINE single #-}
  unionIf :: forall a. SymBool -> ContT r m a -> ContT r m a -> ContT r m a
unionIf SymBool
cond (ContT (a -> m r) -> m r
l) (ContT (a -> m r) -> m r
r) = forall {k} (r :: k) (m :: k -> *) a.
((a -> m r) -> m r) -> ContT r m a
ContT forall a b. (a -> b) -> a -> b
$ \a -> m r
c -> forall (u :: * -> *) a. UnionLike u => SymBool -> u a -> u a -> u a
unionIf SymBool
cond ((a -> m r) -> m r
l a -> m r
c) ((a -> m r) -> m r
r a -> m r
c)
  {-# INLINE unionIf #-}

instance
  (Mergeable s, Mergeable w, Monoid w, Mergeable a, UnionLike 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 = forall (u :: * -> *) a.
(UnionLike u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
  {-# INLINE mrgIte #-}

instance
  (Mergeable s, Mergeable w, Monoid w, UnionLike 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 = forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance
  (Mergeable s, Mergeable w, Monoid w, UnionLike m) =>
  UnionLike (RWSLazy.RWST r w s m)
  where
  mergeWithStrategy :: forall a. MergingStrategy a -> RWST r w s m a -> RWST r w s m a
mergeWithStrategy MergingStrategy a
ms (RWSLazy.RWST r -> s -> m (a, s, w)
f) =
    forall r w s (m :: * -> *) a.
(r -> s -> m (a, s, w)) -> RWST r w s m a
RWSLazy.RWST forall a b. (a -> b) -> a -> b
$ \r
r s
s -> forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> u a -> u a
mergeWithStrategy (forall (u :: * -> * -> * -> *) a b c.
Mergeable3 u =>
MergingStrategy a
-> MergingStrategy b
-> MergingStrategy c
-> MergingStrategy (u a b c)
liftRootStrategy3 MergingStrategy a
ms forall a. Mergeable a => MergingStrategy a
rootStrategy forall a. Mergeable a => MergingStrategy a
rootStrategy) forall a b. (a -> b) -> a -> b
$ r -> s -> m (a, s, w)
f r
r s
s
  {-# INLINE mergeWithStrategy #-}
  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) =
    forall r w s (m :: * -> *) a.
(r -> s -> m (a, s, w)) -> RWST r w s m a
RWSLazy.RWST forall a b. (a -> b) -> a -> b
$ \r
r s
s -> forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall (u :: * -> * -> * -> *) a b c.
Mergeable3 u =>
MergingStrategy a
-> MergingStrategy b
-> MergingStrategy c
-> MergingStrategy (u a b c)
liftRootStrategy3 MergingStrategy a
ms forall a. Mergeable a => MergingStrategy a
rootStrategy 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 #-}
  single :: forall a. a -> RWST r w s m a
single a
x = forall r w s (m :: * -> *) a.
(r -> s -> m (a, s, w)) -> RWST r w s m a
RWSLazy.RWST forall a b. (a -> b) -> a -> b
$ \r
_ s
s -> forall (u :: * -> *) a. UnionLike u => a -> u a
single (a
x, s
s, forall a. Monoid a => a
mempty)
  {-# INLINE single #-}
  unionIf :: forall a.
SymBool -> RWST r w s m a -> RWST r w s m a -> RWST r w s m a
unionIf SymBool
cond (RWSLazy.RWST r -> s -> m (a, s, w)
t) (RWSLazy.RWST r -> s -> m (a, s, w)
f) =
    forall r w s (m :: * -> *) a.
(r -> s -> m (a, s, w)) -> RWST r w s m a
RWSLazy.RWST forall a b. (a -> b) -> a -> b
$ \r
r s
s -> forall (u :: * -> *) a. UnionLike u => SymBool -> u a -> u a -> u a
unionIf 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 unionIf #-}

instance
  (Mergeable s, Mergeable w, Monoid w, Mergeable a, UnionLike 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 = forall (u :: * -> *) a.
(UnionLike u, Mergeable a) =>
SymBool -> u a -> u a -> u a
mrgIf
  {-# INLINE mrgIte #-}

instance
  (Mergeable s, Mergeable w, Monoid w, UnionLike 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 = forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall a. (SymBool -> a -> a -> a) -> MergingStrategy a
SimpleStrategy SymBool -> a -> a -> a
m)
  {-# INLINE liftMrgIte #-}

instance
  (Mergeable s, Mergeable w, Monoid w, UnionLike m) =>
  UnionLike (RWSStrict.RWST r w s m)
  where
  mergeWithStrategy :: forall a. MergingStrategy a -> RWST r w s m a -> RWST r w s m a
mergeWithStrategy MergingStrategy a
ms (RWSStrict.RWST r -> s -> m (a, s, w)
f) =
    forall r w s (m :: * -> *) a.
(r -> s -> m (a, s, w)) -> RWST r w s m a
RWSStrict.RWST forall a b. (a -> b) -> a -> b
$ \r
r s
s -> forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> u a -> u a
mergeWithStrategy (forall (u :: * -> * -> * -> *) a b c.
Mergeable3 u =>
MergingStrategy a
-> MergingStrategy b
-> MergingStrategy c
-> MergingStrategy (u a b c)
liftRootStrategy3 MergingStrategy a
ms forall a. Mergeable a => MergingStrategy a
rootStrategy forall a. Mergeable a => MergingStrategy a
rootStrategy) forall a b. (a -> b) -> a -> b
$ r -> s -> m (a, s, w)
f r
r s
s
  {-# INLINE mergeWithStrategy #-}
  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) =
    forall r w s (m :: * -> *) a.
(r -> s -> m (a, s, w)) -> RWST r w s m a
RWSStrict.RWST forall a b. (a -> b) -> a -> b
$ \r
r s
s -> forall (u :: * -> *) a.
UnionLike u =>
MergingStrategy a -> SymBool -> u a -> u a -> u a
mrgIfWithStrategy (forall (u :: * -> * -> * -> *) a b c.
Mergeable3 u =>
MergingStrategy a
-> MergingStrategy b
-> MergingStrategy c
-> MergingStrategy (u a b c)
liftRootStrategy3 MergingStrategy a
ms forall a. Mergeable a => MergingStrategy a
rootStrategy 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 #-}
  single :: forall a. a -> RWST r w s m a
single a
x = forall r w s (m :: * -> *) a.
(r -> s -> m (a, s, w)) -> RWST r w s m a
RWSStrict.RWST forall a b. (a -> b) -> a -> b
$ \r
_ s
s -> forall (u :: * -> *) a. UnionLike u => a -> u a
single (a
x, s
s, forall a. Monoid a => a
mempty)
  {-# INLINE single #-}
  unionIf :: forall a.
SymBool -> RWST r w s m a -> RWST r w s m a -> RWST r w s m a
unionIf SymBool
cond (RWSStrict.RWST r -> s -> m (a, s, w)
t) (RWSStrict.RWST r -> s -> m (a, s, w)
f) =
    forall r w s (m :: * -> *) a.
(r -> s -> m (a, s, w)) -> RWST r w s m a
RWSStrict.RWST forall a b. (a -> b) -> a -> b
$ \r
r s
s -> forall (u :: * -> *) a. UnionLike u => SymBool -> u a -> u a -> u a
unionIf 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 unionIf #-}

-- | Union containers that can be projected back into single value or
-- if-guarded values.
class (UnionLike u) => UnionPrjOp (u :: Type -> Type) where
  -- | Pattern match to extract single values.
  --
  -- >>> singleView (single 1 :: UnionM Integer)
  -- Just 1
  -- >>> singleView (unionIf "a" (single 1) (single 2) :: UnionM Integer)
  -- Nothing
  singleView :: u a -> Maybe a

  -- | Pattern match to extract if values.
  --
  -- >>> ifView (single 1 :: UnionM Integer)
  -- Nothing
  -- >>> ifView (unionIf "a" (single 1) (single 2) :: UnionM Integer)
  -- Just (a,<1>,<2>)
  -- >>> ifView (mrgIf "a" (single 1) (single 2) :: UnionM Integer)
  -- Just (a,{1},{2})
  ifView :: u a -> Maybe (SymBool, u a, u a)

  -- | The leftmost value in the union.
  --
  -- >>> leftMost (unionIf "a" (single 1) (single 2) :: UnionM Integer)
  -- 1
  leftMost :: u a -> a

-- | Pattern match to extract single values with 'singleView'.
--
-- >>> case (single 1 :: UnionM Integer) of SingleU v -> v
-- 1
pattern SingleU :: UnionPrjOp u => a -> u a
pattern $bSingleU :: forall (u :: * -> *) a. UnionPrjOp u => a -> u a
$mSingleU :: forall {r} {u :: * -> *} {a}.
UnionPrjOp u =>
u a -> (a -> r) -> ((# #) -> r) -> r
SingleU x <-
  (singleView -> Just x)
  where
    SingleU a
x = forall (u :: * -> *) a. UnionLike u => a -> u a
single a
x

-- | Pattern match to extract guard values with 'ifView'
-- >>> case (unionIf "a" (single 1) (single 2) :: UnionM Integer) of IfU c t f -> (c,t,f)
-- (a,<1>,<2>)
pattern IfU :: UnionPrjOp u => SymBool -> u a -> u a -> u a
pattern $bIfU :: forall (u :: * -> *) a.
UnionPrjOp u =>
SymBool -> u a -> u a -> u a
$mIfU :: forall {r} {u :: * -> *} {a}.
UnionPrjOp u =>
u a -> (SymBool -> u a -> u a -> r) -> ((# #) -> r) -> r
IfU c t f <-
  (ifView -> Just (c, t, f))
  where
    IfU SymBool
c u a
t u a
f = forall (u :: * -> *) a. UnionLike u => SymBool -> u a -> u a -> u a
unionIf SymBool
c u a
t u a
f

-- | Merge the simply mergeable values in a union, and extract the merged value.
--
-- In the following example, 'unionIf' will not merge the results, and
-- 'simpleMerge' will merge it and extract the single merged value.
--
-- >>> unionIf (ssym "a") (return $ ssym "b") (return $ ssym "c") :: UnionM SymBool
-- <If a b c>
-- >>> simpleMerge $ (unionIf (ssym "a") (return $ ssym "b") (return $ ssym "c") :: UnionM SymBool)
-- (ite a b c)
simpleMerge :: forall bool u a. (SimpleMergeable a, UnionLike u, UnionPrjOp u) => u a -> a
simpleMerge :: forall bool (u :: * -> *) a.
(SimpleMergeable a, UnionLike u, UnionPrjOp u) =>
u a -> a
simpleMerge u a
u = case forall (u :: * -> *) a. (UnionLike u, Mergeable a) => u a -> u a
merge u a
u of
  SingleU a
x -> a
x
  u a
_ -> forall a. HasCallStack => [Char] -> a
error [Char]
"Should not happen"
{-# INLINE simpleMerge #-}

-- | Lift a function to work on union values.
--
-- >>> sumU = onUnion sum
-- >>> sumU (unionIf "cond" (return ["a"]) (return ["b","c"]) :: UnionM [SymInteger])
-- (ite cond a (+ b c))
onUnion ::
  forall bool u a r.
  (SimpleMergeable r, UnionLike u, UnionPrjOp u, Monad u) =>
  (a -> r) ->
  (u a -> r)
onUnion :: forall bool (u :: * -> *) a r.
(SimpleMergeable r, UnionLike u, UnionPrjOp u, Monad u) =>
(a -> r) -> u a -> r
onUnion a -> r
f = forall bool (u :: * -> *) a.
(SimpleMergeable a, UnionLike u, UnionPrjOp u) =>
u a -> a
simpleMerge forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> r
f

-- | Lift a function to work on union values.
onUnion2 ::
  forall bool u a b r.
  (SimpleMergeable r, UnionLike u, UnionPrjOp u, Monad u) =>
  (a -> b -> r) ->
  (u a -> u b -> r)
onUnion2 :: forall bool (u :: * -> *) a b r.
(SimpleMergeable r, UnionLike u, UnionPrjOp u, Monad u) =>
(a -> b -> r) -> u a -> u b -> r
onUnion2 a -> b -> r
f u a
ua u b
ub = forall bool (u :: * -> *) a.
(SimpleMergeable a, UnionLike u, UnionPrjOp u) =>
u a -> a
simpleMerge forall a b. (a -> b) -> a -> b
$ a -> b -> r
f forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> u a
ua forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> u b
ub

-- | Lift a function to work on union values.
onUnion3 ::
  forall bool u a b c r.
  (SimpleMergeable r, UnionLike u, UnionPrjOp u, Monad u) =>
  (a -> b -> c -> r) ->
  (u a -> u b -> u c -> r)
onUnion3 :: forall bool (u :: * -> *) a b c r.
(SimpleMergeable r, UnionLike u, UnionPrjOp u, Monad u) =>
(a -> b -> c -> r) -> u a -> u b -> u c -> r
onUnion3 a -> b -> c -> r
f u a
ua u b
ub u c
uc = forall bool (u :: * -> *) a.
(SimpleMergeable a, UnionLike u, UnionPrjOp u) =>
u a -> a
simpleMerge forall a b. (a -> b) -> a -> b
$ a -> b -> c -> r
f forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> u a
ua forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> u b
ub forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> u c
uc

-- | Lift a function to work on union values.
onUnion4 ::
  forall bool u a b c d r.
  (SimpleMergeable r, UnionLike u, UnionPrjOp u, Monad u) =>
  (a -> b -> c -> d -> r) ->
  (u a -> u b -> u c -> u d -> r)
onUnion4 :: forall bool (u :: * -> *) a b c d r.
(SimpleMergeable r, UnionLike u, UnionPrjOp u, Monad u) =>
(a -> b -> c -> d -> r) -> u a -> u b -> u c -> u d -> r
onUnion4 a -> b -> c -> d -> r
f u a
ua u b
ub u c
uc u d
ud = forall bool (u :: * -> *) a.
(SimpleMergeable a, UnionLike u, UnionPrjOp u) =>
u a -> a
simpleMerge forall a b. (a -> b) -> a -> b
$ a -> b -> c -> d -> r
f forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> u a
ua forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> u b
ub forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> u c
uc forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> u d
ud

-- | Helper for applying functions on 'UnionPrjOp' and 'SimpleMergeable'.
--
-- >>> let f :: Integer -> UnionM Integer = \x -> mrgIf (ssym "a") (mrgSingle $ x + 1) (mrgSingle $ x + 2)
-- >>> f #~ (mrgIf (ssym "b" :: SymBool) (mrgSingle 0) (mrgSingle 2) :: UnionM Integer)
-- {If (&& b a) 1 (If b 2 (If a 3 4))}
(#~) ::
  (Function f, SimpleMergeable (Ret f), UnionPrjOp u, Functor u) =>
  f ->
  u (Arg f) ->
  Ret f
#~ :: forall f (u :: * -> *).
(Function f, SimpleMergeable (Ret f), UnionPrjOp u, Functor u) =>
f -> u (Arg f) -> Ret f
(#~) f
f u (Arg f)
u = forall bool (u :: * -> *) a.
(SimpleMergeable a, UnionLike u, UnionPrjOp u) =>
u a -> a
simpleMerge forall a b. (a -> b) -> a -> b
$ forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (f
f forall f. Function f => f -> Arg f -> Ret f
#) u (Arg f)
u
{-# INLINE (#~) #-}

infixl 9 #~

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

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

#define SIMPLE_MERGEABLE_SOME_BV(symtype, bf) \
instance SimpleMergeable symtype where \
  mrgIte c = bf (ites c) "mrgIte"; \
  {-# INLINE mrgIte #-}

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

#if 1
SIMPLE_MERGEABLE_SIMPLE(SymBool)
SIMPLE_MERGEABLE_SIMPLE(SymInteger)
SIMPLE_MERGEABLE_BV(SymIntN)
SIMPLE_MERGEABLE_BV(SymWordN)
SIMPLE_MERGEABLE_SOME_BV(SomeSymIntN, binSomeSymIntNR1)
SIMPLE_MERGEABLE_SOME_BV(SomeSymWordN, binSomeSymWordNR1)
SIMPLE_MERGEABLE_FUN(=~>)
SIMPLE_MERGEABLE_FUN(-~>)
#endif