descript-lang-0.2.0.0: src/Descript/Misc/Error/Result/Trans.hs
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}
module Descript.Misc.Error.Result.Trans
( ResultT (..)
, UResultT
, mkSuccessT
, mkFailureT
, mkUFailureT
, maybeToResultT
, mapErrorT
) where
import Descript.Misc.Error.Result.Base
import Control.Monad.Trans.Class
import Core.Control.Monad.Trans
import Control.Monad
-- | Either produces a value and fails, and performs some side effect
-- while doing /either/.
newtype ResultT e u a = ResultT{ runResultT :: u (Result e a) } deriving (Functor)
type UResultT u a = ResultT () u a
instance (Applicative u) => Applicative (ResultT e u) where
pure = ResultT . pure . Success
ResultT f <*> ResultT x = ResultT $ (<*>) <$> f <*> x
instance (Monad u) => Monad (ResultT e u) where
return = ResultT . return . Success
ResultT x >>= f = ResultT $ x >>= f'
where f' (Failure err) = pure $ Failure err
f' (Success val) = runResultT $ f val
instance MonadTrans (ResultT e) where
lift = ResultT . fmap pure
instance MonadHoist (ResultT e) where
mapInner f (ResultT x) = ResultT $ f x
instance (e1 ~ e2) => MonadTransBridge (Result e1) (ResultT e2) where
hoist = ResultT . pure
bindStackOuter f = ResultT . join . fmap (runResultT . f) . runResultT
-- | A lifted success with the given value.
mkSuccessT :: (Monad u) => a -> ResultT e u a
mkSuccessT = hoist . Success
-- | A lifted failure with the given error.
mkFailureT :: (Monad u) => e -> ResultT e u a
mkFailureT = hoist . Failure
-- | A lifted failure with no error details.
mkUFailureT :: (Monad u) => UResultT u a
mkUFailureT = mkFailureT ()
-- | If 'Just', a lifted success. If 'Nothing', a lifted failure with
-- the given error.
maybeToResultT :: (Monad u) => e -> Maybe a -> ResultT e u a
maybeToResultT err = hoist . maybeToResult err
-- | If the result is a 'Failure', transforms the error.
mapErrorT :: (Functor u) => (e1 -> e2) -> ResultT e1 u a -> ResultT e2 u a
mapErrorT = mapResultT . mapError
mapResultT :: (Functor u)
=> (Result e1 a -> Result e2 b)
-> ResultT e1 u a
-> ResultT e2 u b
mapResultT f = ResultT . fmap f . runResultT