    ------------------------------------------------------------------------
    -- | Utilities for the 'Either' type.
    ------------------------------------------------------------------------

    module Agda.Utils.Either
      ( whileLeft
      , caseEitherM
      , mapLeft
      , mapRight
      , traverseEither
      , isLeft
      , isRight
      , fromLeft
      , fromRight
      , fromLeftM
      , fromRightM
      , maybeLeft
      , maybeRight
      , allLeft
      , allRight
      , groupByEither
      , maybeToEither
      , swapEither
      ) where

    import Data.Bifunctor
    import Data.Either (isLeft, isRight)
    import Data.List   (unfoldr)

    import Agda.Utils.List ( spanJust )
    import Agda.Utils.List1 ( List1, pattern (:|), (<|) )
    import qualified Agda.Utils.List1 as List1
    import Agda.Utils.Singleton

    -- | Loop while we have an exception.

    whileLeft :: Monad m => (a -> Either b c) -> (a -> b -> m a) -> (a -> c -> m d) -> a -> m d
    whileLeft :: forall (m :: * -> *) a b c d.
    Monad m =>
    (a -> Either b c) -> (a -> b -> m a) -> (a -> c -> m d) -> a -> m d
    whileLeft a -> Either b c
    test a -> b -> m a
    left a -> c -> m d
    right = a -> m d
    loop where
      loop :: a -> m d
    loop a
    a =
        case a -> Either b c
    test a
    a of
          Left  b
    b -> a -> m d
    loop (a -> m d) -> m a -> m d
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< a -> b -> m a
    left a
    a b
    b
          Right c
    c -> a -> c -> m d
    right a
    a c
    c

    -- | Monadic version of 'either' with a different argument ordering.

    caseEitherM :: Monad m => m (Either a b) -> (a -> m c) -> (b -> m c) -> m c
    caseEitherM :: forall (m :: * -> *) a b c.
    Monad m =>
    m (Either a b) -> (a -> m c) -> (b -> m c) -> m c
    caseEitherM m (Either a b)
    mm a -> m c
    f b -> m c
    g = (a -> m c) -> (b -> m c) -> Either a b -> m c
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either a -> m c
    f b -> m c
    g (Either a b -> m c) -> m (Either a b) -> m c
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< m (Either a b)
    mm

    -- | 'Either _ b' is a functor.

    mapLeft :: (a -> c) -> Either a b -> Either c b
    mapLeft :: forall a c b. (a -> c) -> Either a b -> Either c b
    mapLeft = (a -> c) -> Either a b -> Either c b
    forall (p :: * -> * -> *) a b c.
    Bifunctor p =>
    (a -> b) -> p a c -> p b c
    first

    -- | 'Either a' is a functor.

    mapRight :: (b -> d) -> Either a b -> Either a d
    mapRight :: forall b d a. (b -> d) -> Either a b -> Either a d
    mapRight = (b -> d) -> Either a b -> Either a d
    forall (p :: * -> * -> *) b c a.
    Bifunctor p =>
    (b -> c) -> p a b -> p a c
    second

    -- | 'Either' is bitraversable.
    -- Note: From @base >= 4.10.0.0@ already present in `Data.Bitraversable`.
    traverseEither :: Functor f => (a -> f c) -> (b -> f d) -> Either a b -> f (Either c d)
    traverseEither :: forall (f :: * -> *) a c b d.
    Functor f =>
    (a -> f c) -> (b -> f d) -> Either a b -> f (Either c d)
    traverseEither a -> f c
    f b -> f d
    g = (a -> f (Either c d))
    -> (b -> f (Either c d)) -> Either a b -> f (Either c d)
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either ((c -> Either c d) -> f c -> f (Either c d)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap c -> Either c d
    forall a b. a -> Either a b
    Left (f c -> f (Either c d)) -> (a -> f c) -> a -> f (Either c d)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . a -> f c
    f) ((d -> Either c d) -> f d -> f (Either c d)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap d -> Either c d
    forall a b. b -> Either a b
    Right (f d -> f (Either c d)) -> (b -> f d) -> b -> f (Either c d)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . b -> f d
    g)

    -- | Analogue of 'Data.Maybe.fromMaybe'.
    fromLeft :: (b -> a) -> Either a b -> a
    fromLeft :: forall b a. (b -> a) -> Either a b -> a
    fromLeft = (a -> a
    forall a. a -> a
    id (a -> a) -> (b -> a) -> Either a b -> a
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    `either`)

    -- | Analogue of 'Data.Maybe.fromMaybe'.
    fromRight :: (a -> b) -> Either a b -> b
    fromRight :: forall a b. (a -> b) -> Either a b -> b
    fromRight = ((a -> b) -> (b -> b) -> Either a b -> b
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    `either` b -> b
    forall a. a -> a
    id)

    -- | Analogue of 'Agda.Utils.Maybe.fromMaybeM'.
    fromLeftM :: Monad m => (b -> m a) -> m (Either a b) -> m a
    fromLeftM :: forall (m :: * -> *) b a.
    Monad m =>
    (b -> m a) -> m (Either a b) -> m a
    fromLeftM b -> m a
    f m (Either a b)
    m = (a -> m a) -> (b -> m a) -> Either a b -> m a
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either a -> m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return b -> m a
    f (Either a b -> m a) -> m (Either a b) -> m a
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< m (Either a b)
    m

    -- | Analogue of 'Agda.Utils.Maybe.fromMaybeM'.
    fromRightM :: Monad m => (a -> m b) -> m (Either a b) -> m b
    fromRightM :: forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> m (Either a b) -> m b
    fromRightM a -> m b
    f m (Either a b)
    m = (a -> m b) -> (b -> m b) -> Either a b -> m b
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either a -> m b
    f b -> m b
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Either a b -> m b) -> m (Either a b) -> m b
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<< m (Either a b)
    m

    -- | Safe projection from 'Left'.
    --
    --   > maybeLeft (Left a) = Just a
    --   > maybeLeft Right{}  = Nothing
    --
    maybeLeft :: Either a b -> Maybe a
    maybeLeft :: forall a b. Either a b -> Maybe a
    maybeLeft = (a -> Maybe a) -> (b -> Maybe a) -> Either a b -> Maybe a
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either a -> Maybe a
    forall a. a -> Maybe a
    Just (Maybe a -> b -> Maybe a
    forall a b. a -> b -> a
    const Maybe a
    forall a. Maybe a
    Nothing)

    -- | Safe projection from 'Right'.
    --
    --   > maybeRight (Right b) = Just b
    --   > maybeRight Left{}    = Nothing
    --
    maybeRight :: Either a b -> Maybe b
    maybeRight :: forall a b. Either a b -> Maybe b
    maybeRight = (a -> Maybe b) -> (b -> Maybe b) -> Either a b -> Maybe b
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either (Maybe b -> a -> Maybe b
    forall a b. a -> b -> a
    const Maybe b
    forall a. Maybe a
    Nothing) b -> Maybe b
    forall a. a -> Maybe a
    Just

    -- | Returns @'Just' input_with_tags_stripped@ if all elements are
    -- to the 'Left', and otherwise 'Nothing'.
    allLeft :: [Either a b] -> Maybe [a]
    allLeft :: forall a b. [Either a b] -> Maybe [a]
    allLeft = (Either a b -> Maybe a) -> [Either a b] -> Maybe [a]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    mapM Either a b -> Maybe a
    forall a b. Either a b -> Maybe a
    maybeLeft

    -- | Returns @'Just' input_with_tags_stripped@ if all elements are
    -- to the right, and otherwise 'Nothing'.
    --
    -- @
    --  allRight xs ==
    --    if all isRight xs then
    --      Just (map (\(Right x) -> x) xs)
    --     else
    --      Nothing
    -- @

    allRight :: [Either a b] -> Maybe [b]
    allRight :: forall a b. [Either a b] -> Maybe [b]
    allRight = (Either a b -> Maybe b) -> [Either a b] -> Maybe [b]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    mapM Either a b -> Maybe b
    forall a b. Either a b -> Maybe b
    maybeRight

    -- | Groups a list into alternating chunks of 'Left' and 'Right' values
    groupByEither :: forall a b. [Either a b] -> [Either (List1 a) (List1 b)]
    groupByEither :: forall a b. [Either a b] -> [Either (List1 a) (List1 b)]
    groupByEither = ([Either a b] -> Maybe (Either (List1 a) (List1 b), [Either a b]))
    -> [Either a b] -> [Either (List1 a) (List1 b)]
    forall b a. (b -> Maybe (a, b)) -> b -> [a]
    unfoldr [Either a b] -> Maybe (Either (List1 a) (List1 b), [Either a b])
    c
      where
      c :: [Either a b] -> Maybe (Either (List1 a) (List1 b), [Either a b])
      c :: [Either a b] -> Maybe (Either (List1 a) (List1 b), [Either a b])
    c []             = Maybe (Either (List1 a) (List1 b), [Either a b])
    forall a. Maybe a
    Nothing
      c (Left  a
    a : [Either a b]
    xs) = (Either (List1 a) (List1 b), [Either a b])
    -> Maybe (Either (List1 a) (List1 b), [Either a b])
    forall a. a -> Maybe a
    Just ((Either (List1 a) (List1 b), [Either a b])
     -> Maybe (Either (List1 a) (List1 b), [Either a b]))
    -> (Either (List1 a) (List1 b), [Either a b])
    -> Maybe (Either (List1 a) (List1 b), [Either a b])
    forall a b. (a -> b) -> a -> b
    $ ([a] -> Either (List1 a) (List1 b))
    -> ([a], [Either a b])
    -> (Either (List1 a) (List1 b), [Either a b])
    forall (p :: * -> * -> *) a b c.
    Bifunctor p =>
    (a -> b) -> p a c -> p b c
    first (List1 a -> Either (List1 a) (List1 b)
    forall a b. a -> Either a b
    Left  (List1 a -> Either (List1 a) (List1 b))
    -> ([a] -> List1 a) -> [a] -> Either (List1 a) (List1 b)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (a
    a a -> [a] -> List1 a
    forall a. a -> [a] -> NonEmpty a
    :|)) (([a], [Either a b]) -> (Either (List1 a) (List1 b), [Either a b]))
    -> ([a], [Either a b])
    -> (Either (List1 a) (List1 b), [Either a b])
    forall a b. (a -> b) -> a -> b
    $ (Either a b -> Maybe a) -> [Either a b] -> ([a], [Either a b])
    forall a b. (a -> Maybe b) -> [a] -> (Prefix b, [a])
    spanJust Either a b -> Maybe a
    forall a b. Either a b -> Maybe a
    maybeLeft  [Either a b]
    xs
      c (Right b
    b : [Either a b]
    xs) = (Either (List1 a) (List1 b), [Either a b])
    -> Maybe (Either (List1 a) (List1 b), [Either a b])
    forall a. a -> Maybe a
    Just ((Either (List1 a) (List1 b), [Either a b])
     -> Maybe (Either (List1 a) (List1 b), [Either a b]))
    -> (Either (List1 a) (List1 b), [Either a b])
    -> Maybe (Either (List1 a) (List1 b), [Either a b])
    forall a b. (a -> b) -> a -> b
    $ ([b] -> Either (List1 a) (List1 b))
    -> ([b], [Either a b])
    -> (Either (List1 a) (List1 b), [Either a b])
    forall (p :: * -> * -> *) a b c.
    Bifunctor p =>
    (a -> b) -> p a c -> p b c
    first (List1 b -> Either (List1 a) (List1 b)
    forall a b. b -> Either a b
    Right (List1 b -> Either (List1 a) (List1 b))
    -> ([b] -> List1 b) -> [b] -> Either (List1 a) (List1 b)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (b
    b b -> [b] -> List1 b
    forall a. a -> [a] -> NonEmpty a
    :|)) (([b], [Either a b]) -> (Either (List1 a) (List1 b), [Either a b]))
    -> ([b], [Either a b])
    -> (Either (List1 a) (List1 b), [Either a b])
    forall a b. (a -> b) -> a -> b
    $ (Either a b -> Maybe b) -> [Either a b] -> ([b], [Either a b])
    forall a b. (a -> Maybe b) -> [a] -> (Prefix b, [a])
    spanJust Either a b -> Maybe b
    forall a b. Either a b -> Maybe b
    maybeRight [Either a b]
    xs

    -- | Convert 'Maybe' to @'Either' e@, given an error @e@ for the 'Nothing' case.
    maybeToEither :: e -> Maybe a -> Either e a
    maybeToEither :: forall e a. e -> Maybe a -> Either e a
    maybeToEither e
    e = Either e a -> (a -> Either e a) -> Maybe a -> Either e a
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe (e -> Either e a
    forall a b. a -> Either a b
    Left e
    e) a -> Either e a
    forall a b. b -> Either a b
    Right

    -- | Swap tags 'Left' and 'Right'.
    swapEither :: Either a b -> Either b a
    swapEither :: forall a b. Either a b -> Either b a
    swapEither = (a -> Either b a) -> (b -> Either b a) -> Either a b -> Either b a
    forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
    either a -> Either b a
    forall a b. b -> Either a b
    Right b -> Either b a
    forall a b. a -> Either a b
    Left