{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}

module Argo.Result where

import qualified Argo.Vendor.DeepSeq as DeepSeq
import qualified Control.Applicative as Applicative
import qualified GHC.Generics as Generics

data Result a
    = Failure String
    | Success a
    deriving (Result a -> Result a -> Bool
(Result a -> Result a -> Bool)
-> (Result a -> Result a -> Bool) -> Eq (Result a)
forall a. Eq a => Result a -> Result a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Result a -> Result a -> Bool
$c/= :: forall a. Eq a => Result a -> Result a -> Bool
== :: Result a -> Result a -> Bool
$c== :: forall a. Eq a => Result a -> Result a -> Bool
Eq, (forall x. Result a -> Rep (Result a) x)
-> (forall x. Rep (Result a) x -> Result a) -> Generic (Result a)
forall x. Rep (Result a) x -> Result a
forall x. Result a -> Rep (Result a) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall a x. Rep (Result a) x -> Result a
forall a x. Result a -> Rep (Result a) x
$cto :: forall a x. Rep (Result a) x -> Result a
$cfrom :: forall a x. Result a -> Rep (Result a) x
Generics.Generic, Result a -> ()
(Result a -> ()) -> NFData (Result a)
forall a. NFData a => Result a -> ()
forall a. (a -> ()) -> NFData a
rnf :: Result a -> ()
$crnf :: forall a. NFData a => Result a -> ()
DeepSeq.NFData, Int -> Result a -> ShowS
[Result a] -> ShowS
Result a -> String
(Int -> Result a -> ShowS)
-> (Result a -> String) -> ([Result a] -> ShowS) -> Show (Result a)
forall a. Show a => Int -> Result a -> ShowS
forall a. Show a => [Result a] -> ShowS
forall a. Show a => Result a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Result a] -> ShowS
$cshowList :: forall a. Show a => [Result a] -> ShowS
show :: Result a -> String
$cshow :: forall a. Show a => Result a -> String
showsPrec :: Int -> Result a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Result a -> ShowS
Show)

instance Functor Result where
    fmap :: (a -> b) -> Result a -> Result b
fmap a -> b
f Result a
r = case Result a
r of
        Failure String
e -> String -> Result b
forall a. String -> Result a
Failure String
e
        Success a
x -> b -> Result b
forall a. a -> Result a
Success (b -> Result b) -> b -> Result b
forall a b. (a -> b) -> a -> b
$ a -> b
f a
x

instance Applicative Result where
    pure :: a -> Result a
pure = a -> Result a
forall a. a -> Result a
Success
    Result (a -> b)
rf <*> :: Result (a -> b) -> Result a -> Result b
<*> Result a
rx = case (Result (a -> b)
rf, Result a
rx) of
        (Failure String
e, Result a
_) -> String -> Result b
forall a. String -> Result a
Failure String
e
        (Result (a -> b)
_, Failure String
e) -> String -> Result b
forall a. String -> Result a
Failure String
e
        (Success a -> b
f, Success a
x) -> b -> Result b
forall a. a -> Result a
Success (b -> Result b) -> b -> Result b
forall a b. (a -> b) -> a -> b
$ a -> b
f a
x

instance Monad Result where
    Result a
r >>= :: Result a -> (a -> Result b) -> Result b
>>= a -> Result b
f = case Result a
r of
        Failure String
e -> String -> Result b
forall a. String -> Result a
Failure String
e
        Success a
x -> a -> Result b
f a
x

instance MonadFail Result where
    fail :: String -> Result a
fail = String -> Result a
forall a. String -> Result a
Failure

instance Applicative.Alternative Result where
    empty :: Result a
empty = String -> Result a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"empty"
    Result a
rx <|> :: Result a -> Result a -> Result a
<|> Result a
ry = case Result a
rx of
        Failure String
_ -> Result a
ry
        Success a
_ -> Result a
rx

result :: (String -> b) -> (a -> b) -> Result a -> b
result :: (String -> b) -> (a -> b) -> Result a -> b
result String -> b
f a -> b
g Result a
r = case Result a
r of
    Failure String
e -> String -> b
f String
e
    Success a
x -> a -> b
g a
x