    {- |
       Module      : Text.Pandoc.Readers.Odt.Generic.Fallible
       Copyright   : Copyright (C) 2015 Martin Linnemann
       License     : GNU GPL, version 2 or above

       Maintainer  : Martin Linnemann <theCodingMarlin@googlemail.com>
       Stability   : alpha
       Portability : portable

    Data types and utilities representing failure. Most of it is based on the
    "Either" type in its usual configuration (left represents failure).

    In most cases, the failure type is implied or required to be a "Monoid".

    The choice of "Either" instead of a custom type makes it easier to write
    compatible instances of "ArrowChoice".
    -}

    -- We export everything
    module Text.Pandoc.Readers.Odt.Generic.Fallible where

    -- | Default for now. Will probably become a class at some point.
    type Failure = ()

    type Fallible a = Either Failure a

    --
    maybeToEither :: Maybe a -> Fallible a
    maybeToEither :: Maybe a -> Fallible a
    maybeToEither (Just a :: a
    a) = a -> Fallible a
    forall a b. b -> Either a b
    Right a
    a
    maybeToEither Nothing  = () -> Fallible a
    forall a b. a -> Either a b
    Left  ()

    --
    eitherToMaybe :: Either _l a -> Maybe a
    eitherToMaybe :: Either _l a -> Maybe a
    eitherToMaybe (Left  _) = Maybe a
    forall a. Maybe a
    Nothing
    eitherToMaybe (Right a :: a
    a) = a -> Maybe a
    forall a. a -> Maybe a
    Just a
    a

    -- | > fromLeft f === either f id
    fromLeft :: (a -> b) -> Either a b -> b
    fromLeft :: (a -> b) -> Either a b -> b
    fromLeft f :: a -> b
    f (Left  a :: a
    a) = a -> b
    f a
    a
    fromLeft _ (Right b :: b
    b) = b
    b

    -- | > recover a === fromLeft (const a) === either (const a) id
    recover :: a -> Either _f a -> a
    recover :: a -> Either _f a -> a
    recover a :: a
    a (Left  _) = a
    a
    recover _ (Right a :: a
    a) = a
    a

    -- | I would love to use 'fail'. Alas, 'Monad.fail'...
    failWith :: failure -> Either failure _x
    failWith :: failure -> Either failure _x
    failWith f :: failure
    f = failure -> Either failure _x
    forall a b. a -> Either a b
    Left failure
    f

    --
    failEmpty :: (Monoid failure) => Either failure _x
    failEmpty :: Either failure _x
    failEmpty = failure -> Either failure _x
    forall a b. a -> Either a b
    failWith failure
    forall a. Monoid a => a
    mempty

    --
    succeedWith :: a -> Either _x a
    succeedWith :: a -> Either _x a
    succeedWith = a -> Either _x a
    forall a b. b -> Either a b
    Right

    --
    collapseEither :: Either failure (Either failure x)
                   -> Either failure x
    collapseEither :: Either failure (Either failure x) -> Either failure x
    collapseEither (Left f :: failure
    f         ) = failure -> Either failure x
    forall a b. a -> Either a b
    Left failure
    f
    collapseEither (Right (Left  f :: failure
    f)) = failure -> Either failure x
    forall a b. a -> Either a b
    Left failure
    f
    collapseEither (Right (Right x :: x
    x)) = x -> Either failure x
    forall a b. b -> Either a b
    Right x
    x

    -- | If either of the values represents a  non-error, the result is a
    -- (possibly combined) non-error. If both values represent an error, an error
    -- is returned.
    chooseMax :: (Monoid a, Monoid b) => Either a b -> Either a b -> Either a b
    chooseMax :: Either a b -> Either a b -> Either a b
    chooseMax = (b -> b -> b) -> Either a b -> Either a b -> Either a b
    forall a b.
    Monoid a =>
    (b -> b -> b) -> Either a b -> Either a b -> Either a b
    chooseMaxWith b -> b -> b
    forall a. Monoid a => a -> a -> a
    mappend

    -- | If either of the values represents a non-error, the result is a
    -- (possibly combined) non-error. If both values represent an error, an error
    -- is returned.
    chooseMaxWith :: (Monoid a) => (b -> b -> b)
                                -> Either a b
                                -> Either a b
                                -> Either a b
    chooseMaxWith :: (b -> b -> b) -> Either a b -> Either a b -> Either a b
    chooseMaxWith >< :: b -> b -> b
    (><) (Right a :: b
    a) (Right b :: b
    b) = b -> Either a b
    forall a b. b -> Either a b
    Right (b -> Either a b) -> b -> Either a b
    forall a b. (a -> b) -> a -> b
    $ b
    a b -> b -> b
    >< b
    b
    chooseMaxWith  _   (Left  a :: a
    a) (Left  b :: a
    b) = a -> Either a b
    forall a b. a -> Either a b
    Left  (a -> Either a b) -> a -> Either a b
    forall a b. (a -> b) -> a -> b
    $ a
    a a -> a -> a
    forall a. Monoid a => a -> a -> a
    `mappend` a
    b
    chooseMaxWith  _   (Right a :: b
    a)     _     = b -> Either a b
    forall a b. b -> Either a b
    Right b
    a
    chooseMaxWith  _       _     (Right b :: b
    b) = b -> Either a b
    forall a b. b -> Either a b
    Right b
    b

    -- | Class of containers that can escalate contained 'Either's.
    -- The word "Vector" is meant in the sense of a disease transmitter.
    class ChoiceVector v where
      spreadChoice :: v (Either f a) -> Either f (v a)

    instance ChoiceVector ((,) a) where
      spreadChoice :: (a, Either f a) -> Either f (a, a)
    spreadChoice (_, Left  f :: f
    f) = f -> Either f (a, a)
    forall a b. a -> Either a b
    Left  f
    f
      spreadChoice (x :: a
    x, Right y :: a
    y) = (a, a) -> Either f (a, a)
    forall a b. b -> Either a b
    Right (a
    x,a
    y)
      -- Wasn't there a newtype somewhere with the elements flipped?

    -- | Wrapper for a list. While the normal list instance of 'ChoiceVector'
    -- fails whenever it can, this type will never fail.
    newtype SuccessList a = SuccessList { SuccessList a -> [a]
    collectNonFailing :: [a] }
      deriving ( SuccessList a -> SuccessList a -> Bool
    (SuccessList a -> SuccessList a -> Bool)
    -> (SuccessList a -> SuccessList a -> Bool) -> Eq (SuccessList a)
    forall a. Eq a => SuccessList a -> SuccessList a -> Bool
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: SuccessList a -> SuccessList a -> Bool
    $c/= :: forall a. Eq a => SuccessList a -> SuccessList a -> Bool
    == :: SuccessList a -> SuccessList a -> Bool
    $c== :: forall a. Eq a => SuccessList a -> SuccessList a -> Bool
    Eq, Eq (SuccessList a)
    Eq (SuccessList a) =>
    (SuccessList a -> SuccessList a -> Ordering)
    -> (SuccessList a -> SuccessList a -> Bool)
    -> (SuccessList a -> SuccessList a -> Bool)
    -> (SuccessList a -> SuccessList a -> Bool)
    -> (SuccessList a -> SuccessList a -> Bool)
    -> (SuccessList a -> SuccessList a -> SuccessList a)
    -> (SuccessList a -> SuccessList a -> SuccessList a)
    -> Ord (SuccessList a)
    SuccessList a -> SuccessList a -> Bool
    SuccessList a -> SuccessList a -> Ordering
    SuccessList a -> SuccessList a -> SuccessList a
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    forall a. Ord a => Eq (SuccessList a)
    forall a. Ord a => SuccessList a -> SuccessList a -> Bool
    forall a. Ord a => SuccessList a -> SuccessList a -> Ordering
    forall a. Ord a => SuccessList a -> SuccessList a -> SuccessList a
    min :: SuccessList a -> SuccessList a -> SuccessList a
    $cmin :: forall a. Ord a => SuccessList a -> SuccessList a -> SuccessList a
    max :: SuccessList a -> SuccessList a -> SuccessList a
    $cmax :: forall a. Ord a => SuccessList a -> SuccessList a -> SuccessList a
    >= :: SuccessList a -> SuccessList a -> Bool
    $c>= :: forall a. Ord a => SuccessList a -> SuccessList a -> Bool
    > :: SuccessList a -> SuccessList a -> Bool
    $c> :: forall a. Ord a => SuccessList a -> SuccessList a -> Bool
    <= :: SuccessList a -> SuccessList a -> Bool
    $c<= :: forall a. Ord a => SuccessList a -> SuccessList a -> Bool
    < :: SuccessList a -> SuccessList a -> Bool
    $c< :: forall a. Ord a => SuccessList a -> SuccessList a -> Bool
    compare :: SuccessList a -> SuccessList a -> Ordering
    $ccompare :: forall a. Ord a => SuccessList a -> SuccessList a -> Ordering
    $cp1Ord :: forall a. Ord a => Eq (SuccessList a)
    Ord, Int -> SuccessList a -> ShowS
    [SuccessList a] -> ShowS
    SuccessList a -> String
    (Int -> SuccessList a -> ShowS)
    -> (SuccessList a -> String)
    -> ([SuccessList a] -> ShowS)
    -> Show (SuccessList a)
    forall a. Show a => Int -> SuccessList a -> ShowS
    forall a. Show a => [SuccessList a] -> ShowS
    forall a. Show a => SuccessList a -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [SuccessList a] -> ShowS
    $cshowList :: forall a. Show a => [SuccessList a] -> ShowS
    show :: SuccessList a -> String
    $cshow :: forall a. Show a => SuccessList a -> String
    showsPrec :: Int -> SuccessList a -> ShowS
    $cshowsPrec :: forall a. Show a => Int -> SuccessList a -> ShowS
    Show )

    instance ChoiceVector SuccessList  where
      spreadChoice :: SuccessList (Either f a) -> Either f (SuccessList a)
    spreadChoice = SuccessList a -> Either f (SuccessList a)
    forall a b. b -> Either a b
    Right (SuccessList a -> Either f (SuccessList a))
    -> (SuccessList (Either f a) -> SuccessList a)
    -> SuccessList (Either f a)
    -> Either f (SuccessList a)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [a] -> SuccessList a
    forall a. [a] -> SuccessList a
    SuccessList ([a] -> SuccessList a)
    -> (SuccessList (Either f a) -> [a])
    -> SuccessList (Either f a)
    -> SuccessList a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Either f a -> [a] -> [a]) -> [a] -> [Either f a] -> [a]
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr Either f a -> [a] -> [a]
    forall a a. Either a a -> [a] -> [a]
    unTagRight [] ([Either f a] -> [a])
    -> (SuccessList (Either f a) -> [Either f a])
    -> SuccessList (Either f a)
    -> [a]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . SuccessList (Either f a) -> [Either f a]
    forall a. SuccessList a -> [a]
    collectNonFailing
        where unTagRight :: Either a a -> [a] -> [a]
    unTagRight (Right x :: a
    x) = (a
    xa -> [a] -> [a]
    forall a. a -> [a] -> [a]
    :)
              unTagRight _         = [a] -> [a]
    forall a. a -> a
    id