module Data.Result
( Result
, get, errors
, raise, raiseAll
, accumulate, accumulate_
, fromEither
) where
import Data.Bifunctor
import Data.Bifoldable
import Data.Bitraversable
import Data.Foldable (traverse_)
import Data.Key
import Data.Monoid
newtype Result e a =
Result (Either (e, [e]) a)
deriving (Eq, Ord, Show, Functor, Applicative, Monad, Foldable)
instance Traversable (Result e) where
traverse f (Result x) =
case x of
Left (e, es) ->
pure (Result (Left (e, es)))
Right a ->
Result . Right <$> f a
instance Zip (Result e) where
zipWith f mea meb =
case (mea, meb) of
(Result (Right eaa), Result (Right eba)) ->
Result (Right (f eaa eba))
(Result (Left (e, es)), Result (Left (e', es'))) ->
Result (Left (e, es ++ e' : es'))
(Result (Left ees), _) ->
Result (Left ees)
(_, Result (Left ees)) ->
Result (Left ees)
instance Bifunctor Result where
bimap f g (Result x) =
case x of
Left (e, es) ->
Result (Left (f e, fmap f es))
Right a ->
Result (Right (g a))
instance Bifoldable Result where
bifoldMap f g (Result x) =
case x of
Left (e, es) ->
f e <> foldMap f es
Right a ->
g a
instance Bitraversable Result where
bitraverse f g (Result x) =
case x of
Left (e, es) ->
(\e' es' -> Result (Left (e', es'))) <$> f e <*> traverse f es
Right a ->
Result . Right <$> g a
raise :: e -> Result e a
raise e =
Result (Left (e, []))
raiseAll :: [e] -> Result e ()
raiseAll es =
Result $ case es of
[] ->
Right ()
(e:es') ->
Left (e, es')
get :: Result e a -> Maybe a
get (Result e) =
case e of
Left _ ->
Nothing
Right a ->
Just a
errors :: Result e a -> [e]
errors (Result x) =
case x of
Left (e, es) ->
e:es
Right _ ->
[]
fromEither :: Either e a -> Result e a
fromEither eith =
Result $ case eith of
Left e ->
Left (e, [])
Right a ->
Right a
data AccumulatingResult e a = AccRes { getResult :: Result e a }
instance Functor (AccumulatingResult e) where
fmap f r =
AccRes (fmap f (getResult r))
instance Applicative (AccumulatingResult e) where
pure a =
AccRes (pure a)
x <*> y =
AccRes (getResult x `zap` getResult y)
accumulate :: Traversable t => t (Result e a) -> Result e (t a)
accumulate t =
getResult (traverse AccRes t)
accumulate_ :: Foldable t => t (Result e a) -> Result e ()
accumulate_ t =
getResult (traverse_ AccRes t)