either-n-0.1.0.0: src/Data/Either3/Either3T.hs
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
-- The lifted MonadState, MonadReader, MonadWriter, MonadError and MonadRWS
-- instances fail the coverage condition for their functional dependencies, as
-- mtl's own lifting instances do, and
-- the Data instance has the context Data (f (Either3 a b c)), as a derived
-- instance for a type applied to a type variable must. Each instance context
-- is on a component of the instance head, so instance resolution terminates.
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wall #-}
{- | 'Either3' inside a type constructor @f@, in the same way that @ExceptT e m a@ is @m (Either e a)@.
Use '_Wrapped' to convert between @Either3T f a b c@ and @f (Either3 a b c)@.
-}
module Data.Either3.Either3T (
-- * Data type
Either3T (..),
-- * Isomorphisms
either3Identity,
either3TACB,
either3TBAC,
either3TBCA,
either3TCAB,
either3TCBA,
-- * Type aliases
Either3TIdentity,
Either3TIO,
Either3TMaybe,
Either3TList,
-- * Optics
-- ** Classy lenses
GetEither3T (..),
HasEither3T (..),
-- ** Classy prisms
ReviewEither3T (..),
AsEither3T (..),
) where
import Control.DeepSeq (NFData (..), NFData1 (..))
import Control.Lens (Each (..), FoldableWithIndex (..), FunctorWithIndex (..), Getter, Iso, Lens', Prism', Review, Rewrapped, TraversableWithIndex (..), Unwrapped, Wrapped (..), iso, lens, mapping, prism', review, unto, view, _Unwrapped, _Wrapped)
import Control.Monad.Cont.Class (MonadCont (..))
import Control.Monad.Error.Class (MonadError (..))
import Control.Monad.IO.Class (MonadIO (..))
import Control.Monad.RWS.Class (MonadRWS)
import Control.Monad.Reader.Class (MonadReader (..))
import Control.Monad.State.Class (MonadState (..))
import Control.Monad.Writer.Class (MonadWriter (..))
import Control.Monad.Zip (MonadZip (..))
import Control.Selective (Selective (..), selectM)
import Data.Bifoldable (Bifoldable (..))
import Data.Bifunctor (Bifunctor (..))
import Data.Bifunctor.Swap (Swap (..))
import Data.Bitraversable (Bitraversable (..))
import Data.Data (Data, Typeable)
import Data.Either3.Either3 (
AsEither3 (..),
Either3 (..),
GetEither3 (..),
HasEither3 (..),
ReviewEither3 (..),
either3ACB,
either3BAC,
either3BCA,
either3CAB,
either3CBA,
foldEither3,
)
import Data.Functor.Alt (Alt (..))
import Data.Functor.Apply (Apply (..))
import Data.Functor.Bind (Bind (..))
import Data.Functor.Classes (Eq1 (..), Eq2 (..), Ord1 (..), Ord2 (..), Show1 (..), Show2 (..), compare1, eq1, showsPrec1, showsUnaryWith)
import Data.Functor.Extend (Extend (..))
import Data.Functor.Identity (Identity (..))
import Data.Lens.Injection.Injection1 (Injection1 (..))
import Data.Lens.Injection.Injection2 (Injection2 (..))
import Data.Lens.Injection.Injection3 (Injection3 (..))
import GHC.Generics (Generic, Generic1)
{- $setup
>>> import Control.DeepSeq(rnf)
>>> import Data.Data(toConstr)
>>> import GHC.Generics(from, to)
>>> import Control.Lens((^?), (#), over, view, review, toListOf, _Wrapped)
>>> import Control.Monad.State(State, runState, modify)
>>> import Control.Monad.Reader(Reader, runReader)
>>> import Control.Monad.Writer(Writer, runWriter)
>>> import Control.Monad.Cont(Cont, runCont)
>>> import Control.Monad.Zip(mzip)
>>> import Control.Selective(select)
>>> import Data.Bifunctor(bimap)
>>> import Data.Bifoldable(bifoldMap)
>>> import Data.Bitraversable(bitraverse)
>>> import Data.Bifunctor.Swap(swap)
>>> import Data.Functor.Alt((<!>))
>>> import Data.Functor.Extend(duplicated)
>>> import Data.Functor.Identity(Identity(..))
>>> import Data.Lens.Injection.Injection1(Injection1(..))
>>> import Data.Lens.Injection.Injection2(Injection2(..))
>>> import Data.Lens.Injection.Injection3(Injection3(..))
>>> let e3 = review reviewEither3 :: Either3 String Bool Int -> Either3TIdentity String Bool Int
-}
{- | An 'Either3' inside @f@.
>>> toConstr (Either3T [Third3 1] :: Either3TList String Bool Int)
Either3T
>>> to (from (Either3T [Third3 1] :: Either3TList String Bool Int)) :: Either3TList String Bool Int
Either3T [Third3 1]
-}
newtype Either3T f a b c
= Either3T (f (Either3 a b c))
deriving stock (Generic, Generic1)
deriving stock instance (Typeable f, Data a, Data b, Data c, Data (f (Either3 a b c))) => Data (Either3T f a b c)
-- | 'Either3T' over 'Identity', equivalent to 'Either3'.
type Either3TIdentity = Either3T Identity
-- | 'Either3T' over 'IO'.
type Either3TIO = Either3T IO
-- | 'Either3T' over 'Maybe'.
type Either3TMaybe = Either3T Maybe
-- | 'Either3T' over lists.
type Either3TList = Either3T []
{- | 'Either3' is isomorphic to 'Either3T' over 'Identity'.
>>> view either3Identity (Third3 1 :: Either3 String Bool Int)
Either3T (Identity (Third3 1))
>>> review either3Identity (Either3T (Identity (Second3 True)) :: Either3TIdentity String Bool Int)
Second3 True
It can change the type parameters:
>>> over either3Identity (fmap show) (Third3 1 :: Either3 String Bool Int)
Third3 "1"
-}
either3Identity :: Iso (Either3 a b c) (Either3 a' b' c') (Either3TIdentity a b c) (Either3TIdentity a' b' c')
either3Identity = iso (Either3T . Identity) (runIdentity . view _Wrapped)
{-# INLINE either3Identity #-}
{- | Reorder the type parameters of 'Either3T' to @a c b@, applying 'either3ACB' under @f@.
>>> view either3TACB (Either3T [Second3 True, Third3 1] :: Either3TList String Bool Int)
Either3T [Third3 True,Second3 1]
-}
either3TACB :: (Functor f) => Iso (Either3T f a b c) (Either3T f a' b' c') (Either3T f a c b) (Either3T f a' c' b')
either3TACB =
_Wrapped . mapping either3ACB . _Unwrapped
{-# INLINE either3TACB #-}
{- | Reorder the type parameters of 'Either3T' to @b a c@, applying 'either3BAC' under @f@.
>>> view either3TBAC (Either3T [First3 "x", Second3 True] :: Either3TList String Bool Int)
Either3T [Second3 "x",First3 True]
-}
either3TBAC :: (Functor f) => Iso (Either3T f a b c) (Either3T f a' b' c') (Either3T f b a c) (Either3T f b' a' c')
either3TBAC =
_Wrapped . mapping either3BAC . _Unwrapped
{-# INLINE either3TBAC #-}
{- | Reorder the type parameters of 'Either3T' to @b c a@, applying 'either3BCA' under @f@.
>>> view either3TBCA (Either3T [First3 "x", Second3 True] :: Either3TList String Bool Int)
Either3T [Third3 "x",First3 True]
-}
either3TBCA :: (Functor f) => Iso (Either3T f a b c) (Either3T f a' b' c') (Either3T f b c a) (Either3T f b' c' a')
either3TBCA =
_Wrapped . mapping either3BCA . _Unwrapped
{-# INLINE either3TBCA #-}
{- | Reorder the type parameters of 'Either3T' to @c a b@, applying 'either3CAB' under @f@.
>>> view either3TCAB (Either3T [First3 "x", Third3 1] :: Either3TList String Bool Int)
Either3T [Second3 "x",First3 1]
-}
either3TCAB :: (Functor f) => Iso (Either3T f a b c) (Either3T f a' b' c') (Either3T f c a b) (Either3T f c' a' b')
either3TCAB =
_Wrapped . mapping either3CAB . _Unwrapped
{-# INLINE either3TCAB #-}
{- | Reorder the type parameters of 'Either3T' to @c b a@, applying 'either3CBA' under @f@.
>>> view either3TCBA (Either3T [First3 "x", Third3 1] :: Either3TList String Bool Int)
Either3T [Third3 "x",First3 1]
-}
either3TCBA :: (Functor f) => Iso (Either3T f a b c) (Either3T f a' b' c') (Either3T f c b a) (Either3T f c' b' a')
either3TCBA =
_Wrapped . mapping either3CBA . _Unwrapped
{-# INLINE either3TCBA #-}
{- |
>>> view _Wrapped (Either3T [Third3 1, First3 "x"] :: Either3TList String Bool Int)
[Third3 1,First3 "x"]
>>> review _Wrapped [Second3 True] :: Either3TList String Bool Int
Either3T [Second3 True]
-}
instance Wrapped (Either3T f a b c) where
type Unwrapped (Either3T f a b c) = f (Either3 a b c)
_Wrapped' =
iso (\(Either3T x) -> x) Either3T
{-# INLINE _Wrapped' #-}
{- |
Changes the type constructor from lists to 'Maybe':
>>> over _Wrapped (foldr (const . Just) Nothing) (Either3T [Third3 1, Third3 2] :: Either3TList String Bool Int) :: Either3TMaybe String Bool Int
Either3T (Just (Third3 1))
-}
instance (t ~ Either3T f' a' b' c') => Rewrapped (Either3T f a b c) t
{- |
>>> rnf (Either3T [Third3 1, First3 "x"] :: Either3TList String Bool Int)
()
-}
instance (NFData1 f, NFData a, NFData b, NFData c) => NFData (Either3T f a b c) where
rnf (Either3T x) =
liftRnf rnf x
{-# INLINE rnf #-}
{- |
>>> Either3T [Third3 1] == (Either3T [Third3 1] :: Either3TList String Bool Int)
True
>>> Either3T [Third3 1] == (Either3T [Second3 True] :: Either3TList String Bool Int)
False
-}
instance (Eq1 f, Eq a, Eq b, Eq c) => Eq (Either3T f a b c) where
Either3T x == Either3T y =
eq1 x y
{-# INLINE (==) #-}
instance (Eq1 f, Eq a) => Eq2 (Either3T f a) where
liftEq2 f g (Either3T x) (Either3T y) =
liftEq (liftEq2 f g) x y
{-# INLINE liftEq2 #-}
instance (Eq1 f, Eq a, Eq b) => Eq1 (Either3T f a b) where
liftEq = liftEq2 (==)
{-# INLINE liftEq #-}
{- |
>>> compare (Either3T [First3 "x"]) (Either3T [Third3 1] :: Either3TList String Bool Int)
LT
-}
instance (Ord1 f, Ord a, Ord b, Ord c) => Ord (Either3T f a b c) where
compare (Either3T x) (Either3T y) =
compare1 x y
{-# INLINE compare #-}
instance (Ord1 f, Ord a) => Ord2 (Either3T f a) where
liftCompare2 f g (Either3T x) (Either3T y) =
liftCompare (liftCompare2 f g) x y
{-# INLINE liftCompare2 #-}
instance (Ord1 f, Ord a, Ord b) => Ord1 (Either3T f a b) where
liftCompare = liftCompare2 compare
{-# INLINE liftCompare #-}
{- |
>>> Either3T [Third3 1, First3 "x"] :: Either3TList String Bool Int
Either3T [Third3 1,First3 "x"]
>>> e3 (Second3 True)
Either3T (Identity (Second3 True))
-}
instance (Show1 f, Show a, Show b, Show c) => Show (Either3T f a b c) where
showsPrec d (Either3T x) =
showsUnaryWith showsPrec1 "Either3T" d x
{-# INLINE showsPrec #-}
instance (Show1 f, Show a) => Show2 (Either3T f a) where
liftShowsPrec2 sp1 sl1 sp2 sl2 d (Either3T x) =
showsUnaryWith (liftShowsPrec (liftShowsPrec2 sp1 sl1 sp2 sl2) (liftShowList2 sp1 sl1 sp2 sl2)) "Either3T" d x
{-# INLINE liftShowsPrec2 #-}
instance (Show1 f, Show a, Show b) => Show1 (Either3T f a b) where
liftShowsPrec = liftShowsPrec2 showsPrec showList
{-# INLINE liftShowsPrec #-}
{- | The first value that is 'Third3' wins, otherwise the second value, like 'Either'.
>>> Either3T [First3 "x"] <> Either3T [Third3 1] :: Either3TList String Bool Int
Either3T [Third3 1]
-}
instance (Monad f) => Semigroup (Either3T f a b c) where
(<>) =
(<!>)
{-# INLINE (<>) #-}
{- |
>>> fmap (+ 1) (Either3T [Third3 1, Second3 True] :: Either3TList String Bool Int)
Either3T [Third3 2,Second3 True]
-}
instance (Functor f) => Functor (Either3T f a b) where
fmap =
mapEither3T
{-# INLINE fmap #-}
{- | Runs the effects of the second argument only when the first is 'Third3'.
>>> Either3T [Third3 (+ 1), First3 "x"] <.> Either3T [Third3 1, Third3 2] :: Either3TList String Bool Int
Either3T [Third3 2,Third3 3,First3 "x"]
-}
instance (Monad f) => Apply (Either3T f a b) where
Either3T x <.> Either3T y =
Either3T $
x >>= \case
First3 a -> pure (First3 a)
Second3 b -> pure (Second3 b)
Third3 g -> fmap (fmap g) y
{-# INLINE (<.>) #-}
{- |
>>> pure 1 :: Either3TList String Bool Int
Either3T [Third3 1]
-}
instance (Monad f) => Applicative (Either3T f a b) where
pure =
Either3T . pure . Third3
{-# INLINE pure #-}
(<*>) =
(<.>)
{-# INLINE (<*>) #-}
instance (Monad f) => Bind (Either3T f a b) where
(>>-) =
(>>=)
{-# INLINE (>>-) #-}
{- |
>>> Either3T [Third3 1, Second3 True] >>= (\x -> Either3T [Third3 x, Third3 (x + 1)]) :: Either3TList String Bool Int
Either3T [Third3 1,Third3 2,Second3 True]
-}
instance (Monad f) => Monad (Either3T f a b) where
Either3T x >>= k =
Either3T (x >>= foldEither3 (pure . First3) (pure . Second3) (\c -> let Either3T y = k c in y))
{-# INLINE (>>=) #-}
{- | The first value that is 'Third3' wins, otherwise the second value, like 'Either'.
>>> Either3T [Second3 True] <!> Either3T [Third3 1] :: Either3TList String Bool Int
Either3T [Third3 1]
>>> Either3T [Second3 True] <!> Either3T [First3 "x"] :: Either3TList String Bool Int
Either3T [First3 "x"]
-}
instance (Monad f) => Alt (Either3T f a b) where
Either3T x <!> Either3T y =
Either3T (x >>= foldEither3 (const y) (const y) (pure . Third3))
{-# INLINE (<!>) #-}
{- |
>>> duplicated (Either3T [Third3 1, First3 "x"] :: Either3TList String Bool Int)
Either3T [Third3 (Either3T [Third3 1]),First3 "x"]
-}
instance (Applicative f) => Extend (Either3T f a b) where
duplicated =
fmap (Either3T . pure . Third3)
{-# INLINE duplicated #-}
{- |
>>> select (pure (Left 1)) (pure (+ 1)) :: Either3TList String Bool Int
Either3T [Third3 2]
-}
instance (Monad f) => Selective (Either3T f a b) where
select =
selectM
{-# INLINE select #-}
{- | Lifts 'liftIO' from @f@.
>>> view _Wrapped (liftIO (pure 1) :: Either3TIO String Bool Int)
Third3 1
-}
instance (MonadIO f) => MonadIO (Either3T f a b) where
liftIO =
Either3T . fmap Third3 . liftIO
{-# INLINE liftIO #-}
{- | Lifts 'fail' from @f@.
>>> fail "x" :: Either3TMaybe String Bool Int
Either3T Nothing
-}
instance (MonadFail f) => MonadFail (Either3T f a b) where
fail =
Either3T . fail
{-# INLINE fail #-}
{- | Lifts 'state' from @f@.
>>> runState (view _Wrapped (modify (+ 1) >> get :: Either3T (State Int) String Bool Int)) 1
(Third3 2,2)
-}
instance (MonadState s f) => MonadState s (Either3T f a b) where
state =
Either3T . fmap Third3 . state
{-# INLINE state #-}
{- | Lifts 'ask' and 'local' from @f@, as the instance for @ExceptT@ does.
>>> runReader (view _Wrapped (local (+ 1) ask :: Either3T (Reader Int) String Bool Int)) 1
Third3 2
-}
instance (MonadReader r f) => MonadReader r (Either3T f a b) where
ask =
Either3T (fmap Third3 ask)
{-# INLINE ask #-}
local g (Either3T x) =
Either3T (local g x)
{-# INLINE local #-}
reader =
Either3T . fmap Third3 . reader
{-# INLINE reader #-}
{- | Lifts 'tell', 'listen' and 'pass' from @f@, as the instance for @MaybeT@ does.
>>> runWriter (view _Wrapped (tell [1] >> listen (tell [2] >> pure 'x') :: Either3T (Writer [Int]) String Bool (Char, [Int])))
(Third3 ('x',[2]),[1,2])
>>> runWriter (view _Wrapped (pass (pure ('x', reverse)) <* tell [1, 2] :: Either3T (Writer [Int]) String Bool Char))
(Third3 'x',[1,2])
>>> runWriter (view _Wrapped (pass (tell [1, 2] >> pure ('x', reverse)) :: Either3T (Writer [Int]) String Bool Char))
(Third3 'x',[2,1])
-}
instance (MonadWriter w f) => MonadWriter w (Either3T f a b) where
writer =
Either3T . fmap Third3 . writer
{-# INLINE writer #-}
tell =
Either3T . fmap Third3 . tell
{-# INLINE tell #-}
listen (Either3T x) =
Either3T $ do
(e, w) <- listen x
pure (fmap (,w) e)
{-# INLINE listen #-}
pass (Either3T x) =
Either3T $
pass $ do
e <- x
pure $ case e of
First3 a -> (First3 a, id)
Second3 b -> (Second3 b, id)
Third3 (c, g) -> (Third3 c, g)
{-# INLINE pass #-}
{- | Lifts 'throwError' and 'catchError' from @f@, as the instance for @MaybeT@ does.
'First3' and 'Second3' are values, not errors, so 'catchError' does not catch them.
>>> view _Wrapped (throwError "e" `catchError` (\e -> pure (length e)) :: Either3T (Either String) String Bool Int)
Right (Third3 1)
>>> view _Wrapped (review reviewEither3 (Second3 True) `catchError` (\_ -> pure 1) :: Either3T (Either String) String Bool Int)
Right (Second3 True)
-}
instance (MonadError e f) => MonadError e (Either3T f a b) where
throwError =
Either3T . throwError
{-# INLINE throwError #-}
catchError (Either3T x) h =
Either3T (catchError x (\e -> let Either3T y = h e in y))
{-# INLINE catchError #-}
-- | Lifts 'MonadRWS' from @f@.
instance (MonadRWS r w s f) => MonadRWS r w s (Either3T f a b)
{- | Lifts 'callCC' from @f@, as the instance for @MaybeT@ does.
>>> runCont (view _Wrapped (callCC (\k -> k 1 >> review reviewEither3 (Second3 True)) :: Either3T (Cont r) String Bool Int)) id
Third3 1
-}
instance (MonadCont f) => MonadCont (Either3T f a b) where
callCC g =
Either3T $ callCC $ \k ->
let Either3T y = g (Either3T . k . Third3)
in y
{-# INLINE callCC #-}
{- | Lifts 'mzipWith' from @f@, combining each pair of 'Either3' values with
'Control.Applicative.liftA2', as the instance for @MaybeT@ does.
>>> mzip (Either3T [Third3 1, First3 "x"]) (Either3T [Third3 True, Third3 False]) :: Either3TList String Bool (Int, Bool)
Either3T [Third3 (1,True),First3 "x"]
-}
instance (MonadZip f) => MonadZip (Either3T f a b) where
mzipWith g (Either3T x) (Either3T y) =
Either3T (mzipWith (liftA2 g) x y)
{-# INLINE mzipWith #-}
{- | Maps the second and third type parameters.
>>> bimap not (+ 1) (Either3T [Second3 True, Third3 1] :: Either3TList String Bool Int)
Either3T [Second3 False,Third3 2]
-}
instance (Functor f) => Bifunctor (Either3T f a) where
bimap =
bimapEither3T
{-# INLINE bimap #-}
{- | Swaps the second and third type parameters.
>>> swap (Either3T [Second3 True, Third3 1] :: Either3TList String Bool Int)
Either3T [Third3 True,Second3 1]
-}
instance (Functor f) => Swap (Either3T f a) where
swap (Either3T x) =
Either3T (fmap swap x)
{-# INLINE swap #-}
{- |
>>> sum (Either3T [Third3 1, First3 "x", Third3 2] :: Either3TList String Bool Int)
3
-}
instance (Foldable f) => Foldable (Either3T f a b) where
foldMap =
foldMapEither3T
{-# INLINE foldMap #-}
{- |
>>> traverse (\x -> Just (x + 1)) (Either3T [Third3 1, First3 "x"] :: Either3TList String Bool Int)
Just (Either3T [Third3 2,First3 "x"])
-}
instance (Traversable f) => Traversable (Either3T f a b) where
traverse =
traverseEither3T
{-# INLINE traverse #-}
{- |
>>> bifoldMap show show (Either3T [Second3 True, Third3 1] :: Either3TList String Bool Int)
"True1"
-}
instance (Foldable f) => Bifoldable (Either3T f a) where
bifoldMap =
bifoldMapEither3T
{-# INLINE bifoldMap #-}
{- |
>>> bitraverse (Just . not) (Just . (+ 1)) (Either3T [Second3 True, Third3 1] :: Either3TList String Bool Int)
Just (Either3T [Second3 False,Third3 2])
-}
instance (Traversable f) => Bitraversable (Either3T f a) where
bitraverse =
bitraverseEither3T
{-# INLINE bitraverse #-}
{- Fusion
The 'Functor', 'Foldable', 'Traversable', 'Bifunctor', 'Bifoldable' and
'Bitraversable' methods delegate to the functions below, which are not
inlined before phase 1, so that the rewrite rules, which are active before
phase 1, can fuse compositions of them. Each rule is an instance of the functor law
@fmap f . fmap g = fmap (f . g)@, or of the corresponding law for 'bimap',
'foldMap', 'traverse', 'bifoldMap' or 'bitraverse', for both 'Either3' and
@f@, so the rules assume that the instances for @f@ are lawful.
-}
mapEither3T :: (Functor f) => (c -> d) -> Either3T f a b c -> Either3T f a b d
mapEither3T g (Either3T x) =
Either3T (fmap (fmap g) x)
{-# NOINLINE [1] mapEither3T #-}
bimapEither3T :: (Functor f) => (b -> b') -> (c -> c') -> Either3T f a b c -> Either3T f a b' c'
bimapEither3T g h (Either3T x) =
Either3T (fmap (bimap g h) x)
{-# NOINLINE [1] bimapEither3T #-}
foldMapEither3T :: (Foldable f, Monoid m) => (c -> m) -> Either3T f a b c -> m
foldMapEither3T g (Either3T x) =
foldMap (foldMap g) x
{-# NOINLINE [1] foldMapEither3T #-}
traverseEither3T :: (Traversable f, Applicative g) => (c -> g d) -> Either3T f a b c -> g (Either3T f a b d)
traverseEither3T g (Either3T x) =
Either3T <$> traverse (traverse g) x
{-# NOINLINE [1] traverseEither3T #-}
bifoldMapEither3T :: (Foldable f, Monoid m) => (b -> m) -> (c -> m) -> Either3T f a b c -> m
bifoldMapEither3T g h (Either3T x) =
foldMap (bifoldMap g h) x
{-# NOINLINE [1] bifoldMapEither3T #-}
bitraverseEither3T :: (Traversable f, Applicative g) => (b -> g b') -> (c -> g c') -> Either3T f a b c -> g (Either3T f a b' c')
bitraverseEither3T g h (Either3T x) =
Either3T <$> traverse (bitraverse g h) x
{-# NOINLINE [1] bitraverseEither3T #-}
{-# RULES
"Either3T fmap/fmap" [~1] forall f g x.
mapEither3T f (mapEither3T g x) =
mapEither3T (f . g) x
"Either3T bimap/bimap" [~1] forall f g h k x.
bimapEither3T f g (bimapEither3T h k x) =
bimapEither3T (f . h) (g . k) x
"Either3T fmap/bimap" [~1] forall f g h x.
mapEither3T f (bimapEither3T g h x) =
bimapEither3T g (f . h) x
"Either3T bimap/fmap" [~1] forall f g h x.
bimapEither3T f g (mapEither3T h x) =
bimapEither3T f (g . h) x
"Either3T foldMap/fmap" [~1] forall f g x.
foldMapEither3T f (mapEither3T g x) =
foldMapEither3T (f . g) x
"Either3T traverse/fmap" [~1] forall f g x.
traverseEither3T f (mapEither3T g x) =
traverseEither3T (f . g) x
"Either3T bifoldMap/bimap" [~1] forall f g h k x.
bifoldMapEither3T f g (bimapEither3T h k x) =
bifoldMapEither3T (f . h) (g . k) x
"Either3T bitraverse/bimap" [~1] forall f g h k x.
bitraverseEither3T f g (bimapEither3T h k x) =
bitraverseEither3T (f . h) (g . k) x
#-}
-- | The index is always @()@, as for 'Maybe'.
instance (Functor f) => FunctorWithIndex () (Either3T f a b) where
imap g =
fmap (g ())
{-# INLINE imap #-}
instance (Foldable f) => FoldableWithIndex () (Either3T f a b) where
ifoldMap g =
foldMap (g ())
{-# INLINE ifoldMap #-}
instance (Traversable f) => TraversableWithIndex () (Either3T f a b) where
itraverse g =
traverse (g ())
{-# INLINE itraverse #-}
{- | Traverses every value inside @f@.
>>> toListOf each (Either3T [First3 1, Second3 2, Third3 3] :: Either3TList Int Int Int)
[1,2,3]
-}
instance (Traversable f) => Each (Either3T f a a a) (Either3T f b b b) a b where
each g (Either3T x) =
Either3T <$> traverse (each g) x
{-# INLINE each #-}
{- |
>>> e3 (First3 "x") ^? _I1
Just "x"
-}
instance Injection1 (Either3T Identity a b c) (Either3T Identity a' b c) a a' where
_I1 =
_Wrapped . _Wrapped . _I1
{-# INLINE _I1 #-}
{- |
>>> e3 (Second3 True) ^? _I2
Just True
-}
instance Injection2 (Either3T Identity a b c) (Either3T Identity a b' c) b b' where
_I2 =
_Wrapped . _Wrapped . _I2
{-# INLINE _I2 #-}
{- |
>>> e3 (Third3 1) ^? _I3
Just 1
>>> e3 (First3 "x") ^? _I3
Nothing
-}
instance Injection3 (Either3T Identity a b c) (Either3T Identity a b c') c c' where
_I3 =
_Wrapped . _Wrapped . _I3
{-# INLINE _I3 #-}
{- |
>>> view getEither3 (e3 (Third3 1))
Third3 1
-}
instance GetEither3 (Either3T Identity a b c) a b c where
getEither3 =
_Wrapped . _Wrapped
{-# INLINE getEither3 #-}
{- |
>>> setEither3 (Second3 True) (e3 (Third3 1))
Either3T (Identity (Second3 True))
-}
instance HasEither3 (Either3T Identity a b c) a b c where
setEither3 e _ =
Either3T (Identity e)
{-# INLINE setEither3 #-}
{- | Any 'Either3' can be put in an 'Applicative' @f@.
>>> review reviewEither3 (Second3 True) :: Either3TMaybe String Bool Int
Either3T (Just (Second3 True))
-}
instance (Applicative f) => ReviewEither3 (Either3T f a b c) a b c where
reviewEither3 =
unto (Either3T . pure)
{-# INLINE reviewEither3 #-}
{- |
>>> matchEither3 (e3 (Third3 1))
Just (Third3 1)
>>> e3 (Third3 1) ^? _Either3
Just (Third3 1)
-}
instance AsEither3 (Either3T Identity a b c) a b c where
matchEither3 (Either3T (Identity e)) =
Just e
{-# INLINE matchEither3 #-}
-- | Class for types that can be viewed as an 'Either3T'.
class GetEither3T s f a b c | s -> f a b c where
getEither3T :: Getter s (Either3T f a b c)
instance GetEither3T (Either3T f a b c) f a b c where
getEither3T = id
{-# INLINE getEither3T #-}
{- | Class for types that have a 'Lens'' to an 'Either3T'. Instances define
'setEither3T'; the lens 'either3T' follows from it and from 'getEither3T'.
>>> setEither3T (Either3T [Third3 2]) (Either3T [Third3 1] :: Either3TList String Bool Int)
Either3T [Third3 2]
-}
class (GetEither3T s f a b c) => HasEither3T s f a b c | s -> f a b c where
{-# MINIMAL setEither3T #-}
setEither3T :: Either3T f a b c -> s -> s
either3T :: Lens' s (Either3T f a b c)
either3T = lens (view getEither3T) (flip setEither3T)
{-# INLINE either3T #-}
instance HasEither3T (Either3T f a b c) f a b c where
setEither3T = const
{-# INLINE setEither3T #-}
-- | Class for types that can be constructed from an 'Either3T'.
class ReviewEither3T t f a b c | t -> f a b c where
reviewEither3T :: Review t (Either3T f a b c)
instance ReviewEither3T (Either3T f a b c) f a b c where
reviewEither3T = unto id
{-# INLINE reviewEither3T #-}
{- | Class for types that have a 'Prism'' to an 'Either3T'. Instances define
'matchEither3T'; the prism '_Either3T' follows from it and from 'reviewEither3T'.
>>> matchEither3T (Either3T [Third3 1] :: Either3TList String Bool Int)
Just (Either3T [Third3 1])
-}
class (ReviewEither3T t f a b c) => AsEither3T t f a b c | t -> f a b c where
{-# MINIMAL matchEither3T #-}
matchEither3T :: t -> Maybe (Either3T f a b c)
_Either3T :: Prism' t (Either3T f a b c)
_Either3T = prism' (review reviewEither3T) matchEither3T
{-# INLINE _Either3T #-}
instance AsEither3T (Either3T f a b c) f a b c where
matchEither3T = Just
{-# INLINE matchEither3T #-}