module Control.Monad.Ology.Specific.Result where

import Import

data Result e a
    = SuccessResult a
    | FailureResult e

resultToMaybe :: Result e a -> Maybe a
resultToMaybe :: forall e a. Result e a -> Maybe a
resultToMaybe (SuccessResult a
a) = forall a. a -> Maybe a
Just a
a
resultToMaybe Result e a
_ = forall a. Maybe a
Nothing

resultToM :: MonadFail m => Result String a -> m a
resultToM :: forall (m :: Type -> Type) a. MonadFail m => Result String a -> m a
resultToM (SuccessResult a
a) = forall (m :: Type -> Type) a. Monad m => a -> m a
return a
a
resultToM (FailureResult String
e) = forall (m :: Type -> Type) a. MonadFail m => String -> m a
fail String
e

resultToEither :: Result e a -> Either e a
resultToEither :: forall e a. Result e a -> Either e a
resultToEither (FailureResult e
e) = forall a b. a -> Either a b
Left e
e
resultToEither (SuccessResult a
a) = forall a b. b -> Either a b
Right a
a

eitherToResult :: Either e a -> Result e a
eitherToResult :: forall e a. Either e a -> Result e a
eitherToResult (Left e
e) = forall e a. e -> Result e a
FailureResult e
e
eitherToResult (Right a
a) = forall e a. a -> Result e a
SuccessResult a
a

resultFromMaybe :: e -> Maybe a -> Result e a
resultFromMaybe :: forall e a. e -> Maybe a -> Result e a
resultFromMaybe e
_ (Just a
a) = forall e a. a -> Result e a
SuccessResult a
a
resultFromMaybe e
e Maybe a
Nothing = forall e a. e -> Result e a
FailureResult e
e

maybeToM :: MonadFail m => String -> Maybe a -> m a
maybeToM :: forall (m :: Type -> Type) a.
MonadFail m =>
String -> Maybe a -> m a
maybeToM String
e = forall (m :: Type -> Type) a. MonadFail m => Result String a -> m a
resultToM forall {k} (cat :: k -> k -> Type) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. forall e a. e -> Maybe a -> Result e a
resultFromMaybe String
e

deriving instance (Eq e, Eq a) => Eq (Result e a)

instance Functor (Result e) where
    fmap :: forall a b. (a -> b) -> Result e a -> Result e b
fmap a -> b
ab (SuccessResult a
a) = forall e a. a -> Result e a
SuccessResult (a -> b
ab a
a)
    fmap a -> b
_ (FailureResult e
e) = forall e a. e -> Result e a
FailureResult e
e

instance Foldable (Result e) where
    foldMap :: forall m a. Monoid m => (a -> m) -> Result e a -> m
foldMap a -> m
am (SuccessResult a
a) = a -> m
am a
a
    foldMap a -> m
_ (FailureResult e
_) = forall a. Monoid a => a
mempty

instance Traversable (Result e) where
    traverse :: forall (f :: Type -> Type) a b.
Applicative f =>
(a -> f b) -> Result e a -> f (Result e b)
traverse a -> f b
afb (SuccessResult a
a) = forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap forall e a. a -> Result e a
SuccessResult (a -> f b
afb a
a)
    traverse a -> f b
_ (FailureResult e
e) = forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (forall e a. e -> Result e a
FailureResult e
e)
    sequenceA :: forall (f :: Type -> Type) a.
Applicative f =>
Result e (f a) -> f (Result e a)
sequenceA (SuccessResult f a
fa) = forall (f :: Type -> Type) a b. Functor f => (a -> b) -> f a -> f b
fmap forall e a. a -> Result e a
SuccessResult f a
fa
    sequenceA (FailureResult e
e) = forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (forall e a. e -> Result e a
FailureResult e
e)

instance Applicative (Result e) where
    pure :: forall a. a -> Result e a
pure = forall e a. a -> Result e a
SuccessResult
    (SuccessResult a -> b
ab) <*> :: forall a b. Result e (a -> b) -> Result e a -> Result e b
<*> (SuccessResult a
a) = forall e a. a -> Result e a
SuccessResult (a -> b
ab a
a)
    (SuccessResult a -> b
_) <*> (FailureResult e
e) = forall e a. e -> Result e a
FailureResult e
e
    (FailureResult e
e) <*> Result e a
_ = forall e a. e -> Result e a
FailureResult e
e

instance Monad (Result e) where
    (FailureResult e
e) >>= :: forall a b. Result e a -> (a -> Result e b) -> Result e b
>>= a -> Result e b
_ = forall e a. e -> Result e a
FailureResult e
e
    (SuccessResult a
a) >>= a -> Result e b
amq = a -> Result e b
amq a
a

instance IsString e => MonadFail (Result e) where
    fail :: forall a. String -> Result e a
fail String
s = forall e a. e -> Result e a
FailureResult forall a b. (a -> b) -> a -> b
$ forall a. IsString a => String -> a
fromString String
s

instance Monoid e => Alternative (Result e) where
    empty :: forall a. Result e a
empty = forall e a. e -> Result e a
FailureResult forall a. Monoid a => a
mempty
    (SuccessResult a
a) <|> :: forall a. Result e a -> Result e a -> Result e a
<|> Result e a
_ = forall e a. a -> Result e a
SuccessResult a
a
    (FailureResult e
_) <|> (SuccessResult a
a) = forall e a. a -> Result e a
SuccessResult a
a
    (FailureResult e
e1) <|> (FailureResult e
e2) = forall e a. e -> Result e a
FailureResult forall a b. (a -> b) -> a -> b
$ forall a. Monoid a => a -> a -> a
mappend e
e1 e
e2

instance Monoid e => MonadPlus (Result e)

instance MonadFix (Result e) where
    mfix :: forall a. (a -> Result e a) -> Result e a
mfix a -> Result e a
ama = let
        getSuccess :: Result e a -> a
getSuccess (SuccessResult a
a) = a
a
        getSuccess (FailureResult e
_) = forall a. HasCallStack => String -> a
error String
"mfix FailureResult"
        ma :: Result e a
ma = a -> Result e a
ama forall a b. (a -> b) -> a -> b
$ forall {e} {a}. Result e a -> a
getSuccess Result e a
ma
        in Result e a
ma

instance (Show e, Show a) => Show (Result e a) where
    show :: Result e a -> String
show (SuccessResult a
a) = String
"success: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show a
a
    show (FailureResult e
e) = String
"failure: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show e
e

mapResultFailure :: (e1 -> e2) -> Result e1 a -> Result e2 a
mapResultFailure :: forall e1 e2 a. (e1 -> e2) -> Result e1 a -> Result e2 a
mapResultFailure e1 -> e2
_ (SuccessResult a
a) = forall e a. a -> Result e a
SuccessResult a
a
mapResultFailure e1 -> e2
e1e2 (FailureResult e1
e1) = forall e a. e -> Result e a
FailureResult (e1 -> e2
e1e2 e1
e1)