{-# LANGUAGE CPP                  #-}
{-# LANGUAGE TypeOperators        #-}
{-# OPTIONS_GHC -Wno-deprecations #-}

-- |
-- Module      : Data.Functor.Contravariant.Decide
-- Copyright   : (c) Justin Le 2019
-- License     : BSD3
--
-- Maintainer  : justin@jle.im
-- Stability   : experimental
-- Portability : non-portable
--
-- The contravariant counterpart of 'Alt': like 'Decidable', but without
-- 'Data.Functor.Contravariant.Divisible.loss' or a superclass constraint
-- on 'Divisible'.  This is only a part of this library currently for
-- compatibility, until it is (hopefully) merged into /semigroupoids/.
--
-- @since 0.3.0.0
module Data.Functor.Contravariant.Decide (
    Decide(..)
  , decided
  ) where

import Control.Applicative.Backwards
import Control.Arrow
import Control.Monad.Trans.Identity
import Control.Monad.Trans.List
import Control.Monad.Trans.Maybe
import qualified Control.Monad.Trans.RWS.Lazy as Lazy
import qualified Control.Monad.Trans.RWS.Strict as Strict
import Control.Monad.Trans.Reader
import qualified Control.Monad.Trans.State.Lazy as Lazy
import qualified Control.Monad.Trans.State.Strict as Strict
import qualified Control.Monad.Trans.Writer.Lazy as Lazy
import qualified Control.Monad.Trans.Writer.Strict as Strict

import Data.Either
import Data.Functor.Apply
import Data.Functor.Compose
import Data.Functor.Contravariant
import Data.Functor.Contravariant.Divise
import Data.Functor.Contravariant.Divisible
import Data.Functor.Product
import Data.Functor.Reverse

#if MIN_VERSION_base(4,8,0)
import Data.Monoid (Alt(..))
#else
import Data.Monoid (Monoid(..))
#endif

#if MIN_VERSION_base(4,7,0) || defined(MIN_VERSION_tagged)
import Data.Proxy
#endif

#ifdef MIN_VERSION_StateVar
import Data.StateVar
#endif

#if __GLASGOW_HASKELL__ >= 702
#define GHC_GENERICS
import GHC.Generics
#endif

-- | The contravariant analogue of 'Alt'.
--
-- If one thinks of @f a@ as a consumer of @a@s, then 'decide' allows one
-- to handle the consumption of a value by choosing to handle it via
-- exactly one of two independent consumers.  It redirects the input
-- completely into one of two consumers.
--
-- 'decide' takes the "decision" method and the two potential consumers,
-- and returns the wrapped/combined consumer.
--
-- Mathematically, a functor being an instance of 'Decide' means that it is
-- "semgroupoidal" with respect to the contravariant "either-based" Day
-- convolution (@data EitherDay f g a = forall b c. EitherDay (f b) (g c) (a -> Either b c)@).
-- That is, it is possible to define a function @(f `EitherDay` f) a ->
-- f a@ in a way that is associative.
class Contravariant f => Decide f where
    -- | Takes the "decision" method and the two potential consumers, and
    -- returns the wrapped/combined consumer.
    decide :: (a -> Either b c) -> f b -> f c -> f a

-- | For @'decided' x y@, the resulting @f ('Either' b c)@ will direct
-- 'Left's to be consumed by @x@, and 'Right's to be consumed by y.
decided :: Decide f => f b -> f c -> f (Either b c)
decided :: f b -> f c -> f (Either b c)
decided = (Either b c -> Either b c) -> f b -> f c -> f (Either b c)
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide Either b c -> Either b c
forall a. a -> a
id

instance Decidable f => Decide (WrappedDivisible f) where
    decide :: (a -> Either b c)
-> WrappedDivisible f b
-> WrappedDivisible f c
-> WrappedDivisible f a
decide f :: a -> Either b c
f (WrapDivisible x :: f b
x) (WrapDivisible y :: f c
y) = f a -> WrappedDivisible f a
forall k (f :: k -> *) (a :: k). f a -> WrappedDivisible f a
WrapDivisible ((a -> Either b c) -> f b -> f c -> f a
forall (f :: * -> *) a b c.
Decidable f =>
(a -> Either b c) -> f b -> f c -> f a
choose a -> Either b c
f f b
x f c
y)

instance Decide Comparison where decide :: (a -> Either b c) -> Comparison b -> Comparison c -> Comparison a
decide = (a -> Either b c) -> Comparison b -> Comparison c -> Comparison a
forall (f :: * -> *) a b c.
Decidable f =>
(a -> Either b c) -> f b -> f c -> f a
choose
instance Decide Equivalence where decide :: (a -> Either b c)
-> Equivalence b -> Equivalence c -> Equivalence a
decide = (a -> Either b c)
-> Equivalence b -> Equivalence c -> Equivalence a
forall (f :: * -> *) a b c.
Decidable f =>
(a -> Either b c) -> f b -> f c -> f a
choose
instance Decide Predicate where decide :: (a -> Either b c) -> Predicate b -> Predicate c -> Predicate a
decide = (a -> Either b c) -> Predicate b -> Predicate c -> Predicate a
forall (f :: * -> *) a b c.
Decidable f =>
(a -> Either b c) -> f b -> f c -> f a
choose

-- | Unlike 'Decidable', requires no constraint on @r@
instance Decide (Op r) where
  decide :: (a -> Either b c) -> Op r b -> Op r c -> Op r a
decide f :: a -> Either b c
f (Op g :: b -> r
g) (Op h :: c -> r
h) = (a -> r) -> Op r a
forall a b. (b -> a) -> Op a b
Op ((a -> r) -> Op r a) -> (a -> r) -> Op r a
forall a b. (a -> b) -> a -> b
$ (b -> r) -> (c -> r) -> Either b c -> r
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either b -> r
g c -> r
h (Either b c -> r) -> (a -> Either b c) -> a -> r
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Either b c
f

#if MIN_VERSION_base(4,8,0)
instance Decide f => Decide (Alt f) where
  decide :: (a -> Either b c) -> Alt f b -> Alt f c -> Alt f a
decide f :: a -> Either b c
f (Alt l :: f b
l) (Alt r :: f c
r) = f a -> Alt f a
forall k (f :: k -> *) (a :: k). f a -> Alt f a
Alt (f a -> Alt f a) -> f a -> Alt f a
forall a b. (a -> b) -> a -> b
$ (a -> Either b c) -> f b -> f c -> f a
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide a -> Either b c
f f b
l f c
r
#endif

#ifdef GHC_GENERICS
instance Decide U1 where decide :: (a -> Either b c) -> U1 b -> U1 c -> U1 a
decide = (a -> Either b c) -> U1 b -> U1 c -> U1 a
forall (f :: * -> *) a b c.
Decidable f =>
(a -> Either b c) -> f b -> f c -> f a
choose
instance Decide V1 where decide :: (a -> Either b c) -> V1 b -> V1 c -> V1 a
decide _ = \case {}

instance Decide f => Decide (Rec1 f) where
  decide :: (a -> Either b c) -> Rec1 f b -> Rec1 f c -> Rec1 f a
decide f :: a -> Either b c
f (Rec1 l :: f b
l) (Rec1 r :: f c
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
$ (a -> Either b c) -> f b -> f c -> f a
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide a -> Either b c
f f b
l f c
r

instance Decide f => Decide (M1 i c f) where
  decide :: (a -> Either b c) -> M1 i c f b -> M1 i c f c -> M1 i c f a
decide f :: a -> Either b c
f (M1 l :: f b
l) (M1 r :: f c
r) = f a -> M1 i c f a
forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 (f a -> M1 i c f a) -> f a -> M1 i c f a
forall a b. (a -> b) -> a -> b
$ (a -> Either b c) -> f b -> f c -> f a
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide a -> Either b c
f f b
l f c
r

instance (Decide f, Decide g) => Decide (f :*: g) where
  decide :: (a -> Either b c) -> (:*:) f g b -> (:*:) f g c -> (:*:) f g a
decide f :: a -> Either b c
f (l1 :: f b
l1 :*: r1 :: g b
r1) (l2 :: f c
l2 :*: r2 :: g c
r2) = (a -> Either b c) -> f b -> f c -> f a
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide a -> Either b c
f f b
l1 f c
l2 f a -> g a -> (:*:) f g a
forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
:*: (a -> Either b c) -> g b -> g c -> g a
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide a -> Either b c
f g b
r1 g c
r2

-- | Unlike 'Decidable', requires only 'Apply' on @f@.
instance (Apply f, Decide g) => Decide (f :.: g) where
  decide :: (a -> Either b c) -> (:.:) f g b -> (:.:) f g c -> (:.:) f g a
decide f :: a -> Either b c
f (Comp1 l :: f (g b)
l) (Comp1 r :: f (g c)
r) = f (g a) -> (:.:) f g a
forall k2 k1 (f :: k2 -> *) (g :: k1 -> k2) (p :: k1).
f (g p) -> (:.:) f g p
Comp1 ((g b -> g c -> g a) -> f (g b) -> f (g c) -> f (g a)
forall (f :: * -> *) a b c.
Apply f =>
(a -> b -> c) -> f a -> f b -> f c
liftF2 ((a -> Either b c) -> g b -> g c -> g a
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide a -> Either b c
f) f (g b)
l f (g c)
r)
#endif

instance Decide f => Decide (Backwards f) where
  decide :: (a -> Either b c)
-> Backwards f b -> Backwards f c -> Backwards f a
decide f :: a -> Either b c
f (Backwards l :: f b
l) (Backwards r :: f c
r) = f a -> Backwards f a
forall k (f :: k -> *) (a :: k). f a -> Backwards f a
Backwards (f a -> Backwards f a) -> f a -> Backwards f a
forall a b. (a -> b) -> a -> b
$ (a -> Either b c) -> f b -> f c -> f a
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide a -> Either b c
f f b
l f c
r

instance Decide f => Decide (IdentityT f) where
  decide :: (a -> Either b c)
-> IdentityT f b -> IdentityT f c -> IdentityT f a
decide f :: a -> Either b c
f (IdentityT l :: f b
l) (IdentityT r :: f c
r) = f a -> IdentityT f a
forall k (f :: k -> *) (a :: k). f a -> IdentityT f a
IdentityT (f a -> IdentityT f a) -> f a -> IdentityT f a
forall a b. (a -> b) -> a -> b
$ (a -> Either b c) -> f b -> f c -> f a
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide a -> Either b c
f f b
l f c
r

instance Decide m => Decide (ReaderT r m) where
  decide :: (a -> Either b c)
-> ReaderT r m b -> ReaderT r m c -> ReaderT r m a
decide abc :: a -> Either b c
abc (ReaderT rmb :: r -> m b
rmb) (ReaderT rmc :: r -> m c
rmc) = (r -> m a) -> ReaderT r m a
forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT ((r -> m a) -> ReaderT r m a) -> (r -> m a) -> ReaderT r m a
forall a b. (a -> b) -> a -> b
$ \r :: r
r -> (a -> Either b c) -> m b -> m c -> m a
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide a -> Either b c
abc (r -> m b
rmb r
r) (r -> m c
rmc r
r)

instance Decide m => Decide (Lazy.RWST r w s m) where
  decide :: (a -> Either b c)
-> RWST r w s m b -> RWST r w s m c -> RWST r w s m a
decide abc :: a -> Either b c
abc (Lazy.RWST rsmb :: r -> s -> m (b, s, w)
rsmb) (Lazy.RWST rsmc :: r -> s -> m (c, s, w)
rsmc) = (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
Lazy.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
r s :: s
s ->
    ((a, s, w) -> Either (b, s, w) (c, s, w))
-> m (b, s, w) -> m (c, s, w) -> m (a, s, w)
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide (\ ~(a :: a
a, s' :: s
s', w :: w
w) -> (b -> Either (b, s, w) (c, s, w))
-> (c -> Either (b, s, w) (c, s, w))
-> Either b c
-> Either (b, s, w) (c, s, w)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ((b, s, w) -> Either (b, s, w) (c, s, w)
forall a b. a -> Either a b
Left  ((b, s, w) -> Either (b, s, w) (c, s, w))
-> (b -> (b, s, w)) -> b -> Either (b, s, w) (c, s, w)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> w -> b -> (b, s, w)
forall s w a. s -> w -> a -> (a, s, w)
betuple3 s
s' w
w)
                                    ((c, s, w) -> Either (b, s, w) (c, s, w)
forall a b. b -> Either a b
Right ((c, s, w) -> Either (b, s, w) (c, s, w))
-> (c -> (c, s, w)) -> c -> Either (b, s, w) (c, s, w)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> w -> c -> (c, s, w)
forall s w a. s -> w -> a -> (a, s, w)
betuple3 s
s' w
w)
                                    (a -> Either b c
abc a
a))
           (r -> s -> m (b, s, w)
rsmb r
r s
s) (r -> s -> m (c, s, w)
rsmc r
r s
s)

instance Decide m => Decide (Strict.RWST r w s m) where
  decide :: (a -> Either b c)
-> RWST r w s m b -> RWST r w s m c -> RWST r w s m a
decide abc :: a -> Either b c
abc (Strict.RWST rsmb :: r -> s -> m (b, s, w)
rsmb) (Strict.RWST rsmc :: r -> s -> m (c, s, w)
rsmc) = (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
Strict.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
r s :: s
s ->
    ((a, s, w) -> Either (b, s, w) (c, s, w))
-> m (b, s, w) -> m (c, s, w) -> m (a, s, w)
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide (\(a :: a
a, s' :: s
s', w :: w
w) -> (b -> Either (b, s, w) (c, s, w))
-> (c -> Either (b, s, w) (c, s, w))
-> Either b c
-> Either (b, s, w) (c, s, w)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ((b, s, w) -> Either (b, s, w) (c, s, w)
forall a b. a -> Either a b
Left  ((b, s, w) -> Either (b, s, w) (c, s, w))
-> (b -> (b, s, w)) -> b -> Either (b, s, w) (c, s, w)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> w -> b -> (b, s, w)
forall s w a. s -> w -> a -> (a, s, w)
betuple3 s
s' w
w)
                                  ((c, s, w) -> Either (b, s, w) (c, s, w)
forall a b. b -> Either a b
Right ((c, s, w) -> Either (b, s, w) (c, s, w))
-> (c -> (c, s, w)) -> c -> Either (b, s, w) (c, s, w)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> w -> c -> (c, s, w)
forall s w a. s -> w -> a -> (a, s, w)
betuple3 s
s' w
w)
                                  (a -> Either b c
abc a
a))
           (r -> s -> m (b, s, w)
rsmb r
r s
s) (r -> s -> m (c, s, w)
rsmc r
r s
s)

instance Divise m => Decide (ListT m) where
  decide :: (a -> Either b c) -> ListT m b -> ListT m c -> ListT m a
decide f :: a -> Either b c
f (ListT l :: m [b]
l) (ListT r :: m [c]
r) = m [a] -> ListT m a
forall (m :: * -> *) a. m [a] -> ListT m a
ListT (m [a] -> ListT m a) -> m [a] -> ListT m a
forall a b. (a -> b) -> a -> b
$ ([a] -> ([b], [c])) -> m [b] -> m [c] -> m [a]
forall (f :: * -> *) a b c.
Divise f =>
(a -> (b, c)) -> f b -> f c -> f a
divise (([Either b c] -> [b]
forall a b. [Either a b] -> [a]
lefts ([Either b c] -> [b])
-> ([Either b c] -> [c]) -> [Either b c] -> ([b], [c])
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& [Either b c] -> [c]
forall a b. [Either a b] -> [b]
rights) ([Either b c] -> ([b], [c]))
-> ([a] -> [Either b c]) -> [a] -> ([b], [c])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Either b c) -> [a] -> [Either b c]
forall a b. (a -> b) -> [a] -> [b]
map a -> Either b c
f) m [b]
l m [c]
r

instance Divise m => Decide (MaybeT m) where
  decide :: (a -> Either b c) -> MaybeT m b -> MaybeT m c -> MaybeT m a
decide f :: a -> Either b c
f (MaybeT l :: m (Maybe b)
l) (MaybeT r :: m (Maybe c)
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
$
    (Maybe a -> (Maybe b, Maybe c))
-> m (Maybe b) -> m (Maybe c) -> m (Maybe a)
forall (f :: * -> *) a b c.
Divise f =>
(a -> (b, c)) -> f b -> f c -> f a
divise ( (Maybe b, Maybe c)
-> (a -> (Maybe b, Maybe c)) -> Maybe a -> (Maybe b, Maybe c)
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Maybe b
forall a. Maybe a
Nothing, Maybe c
forall a. Maybe a
Nothing)
                   ((b -> (Maybe b, Maybe c))
-> (c -> (Maybe b, Maybe c)) -> Either b c -> (Maybe b, Maybe c)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (\b :: b
b -> (b -> Maybe b
forall a. a -> Maybe a
Just b
b, Maybe c
forall a. Maybe a
Nothing))
                           (\c :: c
c -> (Maybe b
forall a. Maybe a
Nothing, c -> Maybe c
forall a. a -> Maybe a
Just c
c)) (Either b c -> (Maybe b, Maybe c))
-> (a -> Either b c) -> a -> (Maybe b, Maybe c)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Either b c
f)
           ) m (Maybe b)
l m (Maybe c)
r

instance Decide m => Decide (Lazy.StateT s m) where
  decide :: (a -> Either b c) -> StateT s m b -> StateT s m c -> StateT s m a
decide f :: a -> Either b c
f (Lazy.StateT l :: s -> m (b, s)
l) (Lazy.StateT r :: s -> m (c, s)
r) = (s -> m (a, s)) -> StateT s m a
forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
Lazy.StateT ((s -> m (a, s)) -> StateT s m a)
-> (s -> m (a, s)) -> StateT s m a
forall a b. (a -> b) -> a -> b
$ \s :: s
s ->
    ((a, s) -> Either (b, s) (c, s))
-> m (b, s) -> m (c, s) -> m (a, s)
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide (\ ~(a :: a
a, s' :: s
s') -> (b -> Either (b, s) (c, s))
-> (c -> Either (b, s) (c, s))
-> Either b c
-> Either (b, s) (c, s)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ((b, s) -> Either (b, s) (c, s)
forall a b. a -> Either a b
Left ((b, s) -> Either (b, s) (c, s))
-> (b -> (b, s)) -> b -> Either (b, s) (c, s)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> b -> (b, s)
forall s a. s -> a -> (a, s)
betuple s
s') ((c, s) -> Either (b, s) (c, s)
forall a b. b -> Either a b
Right ((c, s) -> Either (b, s) (c, s))
-> (c -> (c, s)) -> c -> Either (b, s) (c, s)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> c -> (c, s)
forall s a. s -> a -> (a, s)
betuple s
s') (a -> Either b c
f a
a))
           (s -> m (b, s)
l s
s) (s -> m (c, s)
r s
s)

instance Decide m => Decide (Strict.StateT s m) where
  decide :: (a -> Either b c) -> StateT s m b -> StateT s m c -> StateT s m a
decide f :: a -> Either b c
f (Strict.StateT l :: s -> m (b, s)
l) (Strict.StateT r :: s -> m (c, s)
r) = (s -> m (a, s)) -> StateT s m a
forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
Strict.StateT ((s -> m (a, s)) -> StateT s m a)
-> (s -> m (a, s)) -> StateT s m a
forall a b. (a -> b) -> a -> b
$ \s :: s
s ->
    ((a, s) -> Either (b, s) (c, s))
-> m (b, s) -> m (c, s) -> m (a, s)
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide (\(a :: a
a, s' :: s
s') -> (b -> Either (b, s) (c, s))
-> (c -> Either (b, s) (c, s))
-> Either b c
-> Either (b, s) (c, s)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ((b, s) -> Either (b, s) (c, s)
forall a b. a -> Either a b
Left ((b, s) -> Either (b, s) (c, s))
-> (b -> (b, s)) -> b -> Either (b, s) (c, s)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> b -> (b, s)
forall s a. s -> a -> (a, s)
betuple s
s') ((c, s) -> Either (b, s) (c, s)
forall a b. b -> Either a b
Right ((c, s) -> Either (b, s) (c, s))
-> (c -> (c, s)) -> c -> Either (b, s) (c, s)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. s -> c -> (c, s)
forall s a. s -> a -> (a, s)
betuple s
s') (a -> Either b c
f a
a))
           (s -> m (b, s)
l s
s) (s -> m (c, s)
r s
s)

instance Decide m => Decide (Lazy.WriterT w m) where
  decide :: (a -> Either b c)
-> WriterT w m b -> WriterT w m c -> WriterT w m a
decide f :: a -> Either b c
f (Lazy.WriterT l :: m (b, w)
l) (Lazy.WriterT r :: m (c, w)
r) = m (a, w) -> WriterT w m a
forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
Lazy.WriterT (m (a, w) -> WriterT w m a) -> m (a, w) -> WriterT w m a
forall a b. (a -> b) -> a -> b
$
    ((a, w) -> Either (b, w) (c, w))
-> m (b, w) -> m (c, w) -> m (a, w)
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide (\ ~(a :: a
a, s' :: w
s') -> (b -> Either (b, w) (c, w))
-> (c -> Either (b, w) (c, w))
-> Either b c
-> Either (b, w) (c, w)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ((b, w) -> Either (b, w) (c, w)
forall a b. a -> Either a b
Left ((b, w) -> Either (b, w) (c, w))
-> (b -> (b, w)) -> b -> Either (b, w) (c, w)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. w -> b -> (b, w)
forall s a. s -> a -> (a, s)
betuple w
s') ((c, w) -> Either (b, w) (c, w)
forall a b. b -> Either a b
Right ((c, w) -> Either (b, w) (c, w))
-> (c -> (c, w)) -> c -> Either (b, w) (c, w)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. w -> c -> (c, w)
forall s a. s -> a -> (a, s)
betuple w
s') (a -> Either b c
f a
a)) m (b, w)
l m (c, w)
r

instance Decide m => Decide (Strict.WriterT w m) where
  decide :: (a -> Either b c)
-> WriterT w m b -> WriterT w m c -> WriterT w m a
decide f :: a -> Either b c
f (Strict.WriterT l :: m (b, w)
l) (Strict.WriterT r :: m (c, w)
r) = m (a, w) -> WriterT w m a
forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
Strict.WriterT (m (a, w) -> WriterT w m a) -> m (a, w) -> WriterT w m a
forall a b. (a -> b) -> a -> b
$
    ((a, w) -> Either (b, w) (c, w))
-> m (b, w) -> m (c, w) -> m (a, w)
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide (\(a :: a
a, s' :: w
s') -> (b -> Either (b, w) (c, w))
-> (c -> Either (b, w) (c, w))
-> Either b c
-> Either (b, w) (c, w)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ((b, w) -> Either (b, w) (c, w)
forall a b. a -> Either a b
Left ((b, w) -> Either (b, w) (c, w))
-> (b -> (b, w)) -> b -> Either (b, w) (c, w)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. w -> b -> (b, w)
forall s a. s -> a -> (a, s)
betuple w
s') ((c, w) -> Either (b, w) (c, w)
forall a b. b -> Either a b
Right ((c, w) -> Either (b, w) (c, w))
-> (c -> (c, w)) -> c -> Either (b, w) (c, w)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. w -> c -> (c, w)
forall s a. s -> a -> (a, s)
betuple w
s') (a -> Either b c
f a
a)) m (b, w)
l m (c, w)
r

-- | Unlike 'Decidable', requires only 'Apply' on @f@.
instance (Apply f, Decide g) => Decide (Compose f g) where
  decide :: (a -> Either b c)
-> Compose f g b -> Compose f g c -> Compose f g a
decide f :: a -> Either b c
f (Compose l :: f (g b)
l) (Compose r :: f (g c)
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 ((g b -> g c -> g a) -> f (g b) -> f (g c) -> f (g a)
forall (f :: * -> *) a b c.
Apply f =>
(a -> b -> c) -> f a -> f b -> f c
liftF2 ((a -> Either b c) -> g b -> g c -> g a
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide a -> Either b c
f) f (g b)
l f (g c)
r)

instance (Decide f, Decide g) => Decide (Product f g) where
  decide :: (a -> Either b c)
-> Product f g b -> Product f g c -> Product f g a
decide f :: a -> Either b c
f (Pair l1 :: f b
l1 r1 :: g b
r1) (Pair l2 :: f c
l2 r2 :: g c
r2) = f a -> g a -> Product f g a
forall k (f :: k -> *) (g :: k -> *) (a :: k).
f a -> g a -> Product f g a
Pair ((a -> Either b c) -> f b -> f c -> f a
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide a -> Either b c
f f b
l1 f c
l2) ((a -> Either b c) -> g b -> g c -> g a
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide a -> Either b c
f g b
r1 g c
r2)

instance Decide f => Decide (Reverse f) where
  decide :: (a -> Either b c) -> Reverse f b -> Reverse f c -> Reverse f a
decide f :: a -> Either b c
f (Reverse l :: f b
l) (Reverse r :: f c
r) = f a -> Reverse f a
forall k (f :: k -> *) (a :: k). f a -> Reverse f a
Reverse (f a -> Reverse f a) -> f a -> Reverse f a
forall a b. (a -> b) -> a -> b
$ (a -> Either b c) -> f b -> f c -> f a
forall (f :: * -> *) a b c.
Decide f =>
(a -> Either b c) -> f b -> f c -> f a
decide a -> Either b c
f f b
l f c
r

betuple :: s -> a -> (a, s)
betuple :: s -> a -> (a, s)
betuple s :: s
s a :: a
a = (a
a, s
s)

betuple3 :: s -> w -> a -> (a, s, w)
betuple3 :: s -> w -> a -> (a, s, w)
betuple3 s :: s
s w :: w
w a :: a
a = (a
a, s
s, w
w)

#if MIN_VERSION_base(4,7,0) || defined(MIN_VERSION_tagged)
instance Decide Proxy where
  decide :: (a -> Either b c) -> Proxy b -> Proxy c -> Proxy a
decide _ Proxy Proxy = Proxy a
forall k (t :: k). Proxy t
Proxy
#endif

#ifdef MIN_VERSION_StateVar
instance Decide SettableStateVar where
  decide k (SettableStateVar l) (SettableStateVar r) = SettableStateVar $ \ a -> case k a of
    Left b -> l b
    Right c -> r c
#endif