transformers-convert-0.2.0.0: src/Control/Monad/Trans/Convert.hs
{-# LANGUAGE NoMonomorphismRestriction #-}
module Control.Monad.Trans.Convert
( -- ** to MaybeT
mMaybeToMaybeT
, mMToMT
, ioMaybeToMaybeT
, ioMToMT
, mEitherToMaybeT
, mEToMT
, ioEitherToMaybeT
, ioEToMT
, mPairToMaybeT
, mPairToMaybeT'
, mPairFstToMaybeT
, mPairSndToMaybeT
, mMonoidToMaybeT
, mOToMT
, mBoolToMaybeT
, mBToMT
, tryIOMonoidToMaybeT
, tryIOMT
-- ** toEitherT
, mMaybeToEitherT
, mMToET
, ioMaybeToEitherT
, ioMToET
, mEitherToEitherT
, mEToET
, ioEitherToEitherT
, ioEToET
, mPairToEitherT
, mPairToEitherT'
, mPairBothToEitherT
, mMonoidToEitherT
, mOToET
, mBoolToEitherT
, mBToET
, fmapLeftT
, fmapRightT
, tryIOMonoidToEitherT
, tryIOET
, tryIOET'
) where
import Data.Easy
import Data.Monoid
import Control.Applicative
{-import Control.Monad-}
import Control.Monad.Trans.Class
import Control.Monad.Trans.Maybe
import Control.Monad.Trans.Either
import Control.Exception
import System.IO.Error
------------------------------------------------------------------------------
-- Maybe ---------------------------------------------------------------------
------------------------------------------------------------------------------
-- | Lift a 'Maybe' to the 'MaybeT' monad
-- Shamelessly copied from "Control.Error.Util"
hoistMaybe :: (Monad m) => Maybe b -> MaybeT m b
hoistMaybe = MaybeT . return
-- | Analogous to 'Just' and equivalent to 'return'
{-just :: (Monad m) => a -> MaybeT m a-}
{-just a = MaybeT (return (Just a))-}
-- | Analogous to 'Nothing' and equivalent to 'mzero'
nothing :: (Monad m) => MaybeT m a
nothing = MaybeT (return Nothing)
-- | Transform a maybe value encapsulated in a @Monad m@ into the equivalent
-- MaybeT m monad transformer.
--
-- /NOTE/: this is not equivalent to either @lift@ or @hoistMaybe@ alone.
-- Check the types carefully.
mMaybeToMaybeT :: (Monad m) => m (Maybe a) -> MaybeT m a
mMaybeToMaybeT mF = lift mF >>= hoistMaybe
-- | Shorter alias for mMaybeToMaybeT
mMToMT :: (Monad m) => m (Maybe a) -> MaybeT m a
mMToMT = mMaybeToMaybeT
-- | Transform a IO (Maybe a) value into a MaybeT IO a value
ioMaybeToMaybeT :: IO (Maybe a) -> MaybeT IO a
ioMaybeToMaybeT = mMaybeToMaybeT
-- | Shorter alias for ioMaybeToMaybeT
ioMToMT :: IO (Maybe a) -> MaybeT IO a
ioMToMT = ioMaybeToMaybeT
-- | Transform a either value encapsulated in a @Monad m@ into the equivalent
-- MaybeT m monad transformer.
--
-- /Note/: The left value is silently discarded.
mEitherToMaybeT :: (Functor m) => m (Either a b) -> MaybeT m b
{-mEitherToMaybeT eF = eitherToMaybe <$> lift eF >>= hoistMaybe-}
mEitherToMaybeT eF = MaybeT (eitherToMaybe <$> eF)
-- (!?) :: Applicative m => m (Maybe a) -> e -> EitherT e m a
-- (!?) a e = EitherT (note e <$> a)
-- hoistMaybe = MaybeT . return
-- | Shorter alias for 'mEitherToMaybeT'.
mEToMT :: (Functor m, Monad m) => m (Either a b) -> MaybeT m b
mEToMT = mEitherToMaybeT
-- | Transform a either value encapsulated in a IO monad into the equivalent
-- MaybeT IO monad transformer.
--
-- /Note/: The left value is silently discarded.
ioEitherToMaybeT :: IO (Either a b) -> MaybeT IO b
ioEitherToMaybeT = mEitherToMaybeT
-- | Shorter alias for 'mEitherToMaybeT'.
ioEToMT :: IO (Either a b) -> MaybeT IO b
ioEToMT = mEitherToMaybeT
-- | Case analysis of a pair of monoid values returned by a monad into
-- a MaybeT value.
-- The value conversion is done by @'pairToMaybe'@.
mPairToMaybeT :: (Eq a, Monoid a, Functor m, Monad m) => m (a,a) -> MaybeT m a
mPairToMaybeT pF = pairToMaybe <$> lift pF >>= hoistMaybe
-- | Case analysis of a pair of monoid values returned by a monad into
-- a MaybeT value.
-- The value conversion is done by @'pairToMaybe''@.
mPairToMaybeT' :: (Eq a, Monoid a, Functor m, Monad m) => m (a,a) -> MaybeT m a
mPairToMaybeT' pF = pairToMaybe' <$> lift pF >>= hoistMaybe
-- | Case analysis of a pair of monoid values returned by a monad into
-- a MaybeT value.
-- The value conversion is done by @'pairFstToMaybe'@.
mPairFstToMaybeT :: (Eq a, Monoid a, Functor m, Monad m) => m (a,b) -> MaybeT m a
mPairFstToMaybeT pF = pairFstToMaybe <$> lift pF >>= hoistMaybe
-- | Case analysis of a pair of monoid values returned by a monad into
-- a MaybeT value.
-- The value conversion is done by @'pairSndToMaybe'@.
mPairSndToMaybeT :: (Eq b, Monoid b, Functor m, Monad m) => m (a,b) -> MaybeT m b
mPairSndToMaybeT pF = pairSndToMaybe <$> lift pF >>= hoistMaybe
-- | Transform a monoid value encapsulated in a @Monad m@ into the equivalent
-- MaybeT m monad transformer (@'mempty'@ -> @'Nothing'@).
mMonoidToMaybeT :: (Eq o, Monoid o, Functor m, Monad m) => m o -> MaybeT m o
mMonoidToMaybeT oF = monoidToMaybe <$> lift oF >>= hoistMaybe
-- | Shorter alias for 'mMonoidToMaybeT'
mOToMT :: (Eq o, Monoid o, Functor m, Monad m) => m o -> MaybeT m o
mOToMT = mMonoidToMaybeT
-- | Transform a boolean value encapsulated in a @Monad m@ into the equivalent
-- MaybeT m monad transformer (@'True'@ -> @Provided Default Value@).
mBoolToMaybeT :: (Functor m, Monad m) => a -> m Bool -> MaybeT m a
mBoolToMaybeT def bF = boolToMaybe def <$> lift bF >>= hoistMaybe
-- | Shorter alias for @'mBoolToMaybeT'@.
mBToMT :: (Functor m, Monad m) => a -> m Bool -> MaybeT m a
mBToMT = mBoolToMaybeT
-- This function executes an IO action that returns a monoid value, or raises
-- a @'IOException'@. If a @'IOException'@ is raised, or the return value
-- is an empty monoid, the function returns @'Nothing'@ in the
-- @MaybeT IO@ monad transformer.
--
-- /Note/: if a different type of exception is raised (@/= IOEXCEPTION@),
-- then that exception is re-thrown.
tryIOMonoidToMaybeT
:: (Eq a, Monoid a)
=> IO a
-> MaybeT IO a
tryIOMonoidToMaybeT ioF = do
{-join . fmap monoidToMaybe . eitherToMaybe-}
{-<$> (lift . tryIOError) ioF-}
{->>= hoistMaybe-}
res <- lift . tryIOError $ ioF
case res of
Left _ -> nothing
Right a -> hoistMaybe $ monoidToMaybe a
-- A shorter alias for @'tryIOMonoidToMaybeT'@.
tryIOMT
:: (Eq a, Monoid a)
=> IO a
-> MaybeT IO a
tryIOMT = tryIOMonoidToMaybeT
------------------------------------------------------------------------------
-- Either --------------------------------------------------------------------
------------------------------------------------------------------------------
{-ioMaybeToEitherT :: b -> IO (Maybe a) -> EitherT b IO a-}
{-ioMaybeToEitherT err ioF = maybeToEither err <$> liftIO ioF >>= hoistEither-}
-- | Transform a maybe value encapsulated in a @Monad m@ into the equivalent
-- EitherT b m monad transformer.
--
-- /NOTE/: this is not equivalent to either @lift@ or @hoistEither@ alone.
-- Check the types carefully.
mMaybeToEitherT :: (Monad m) => b -> m (Maybe a) -> EitherT b m a
mMaybeToEitherT err mF = maybeToEither err <$> lift mF >>= hoistEither
-- | Shorter alias for mMaybeToEitherT
mMToET :: (Monad m) => b -> m (Maybe a) -> EitherT b m a
mMToET = mMaybeToEitherT
-- | Transform a IO (Maybe a) value into a EitherT b IO a value
ioMaybeToEitherT :: b -> IO (Maybe a) -> EitherT b IO a
ioMaybeToEitherT = mMaybeToEitherT
-- | Shorter alias for ioMaybeToEitherT
ioMToET :: b -> IO (Maybe a) -> EitherT b IO a
ioMToET = ioMaybeToEitherT
-- | Transform a either value encapsulated in a @Monad m@ into the equivalent
-- EitherT e m monad transformer.
mEitherToEitherT :: Monad m => m (Either b a) -> EitherT b m a
mEitherToEitherT eF = lift eF >>= hoistEither
-- | Shorter alias for 'mEitherToEitherT'.
mEToET :: Monad m => m (Either b a) -> EitherT b m a
mEToET = mEitherToEitherT
-- | Transform a either value encapsulated in a IO monad into the equivalent
-- EitherT b IO monad transformer.
ioEitherToEitherT :: IO (Either b a) -> EitherT b IO a
ioEitherToEitherT = mEitherToEitherT
-- | Shorter alias for 'mEitherToEitherT'.
ioEToET :: IO (Either b a) -> EitherT b IO a
ioEToET = mEitherToEitherT
-- | Case analysis of a pair of monoid values returned by a monad into
-- a EitherT value.
-- The value conversion is done by @'pairToEither'@.
mPairToEitherT
:: (Eq a, Monoid a, Functor m, Monad m)
=> m (b,a)
-> EitherT b m a
mPairToEitherT pF = pairToEither <$> lift pF >>= hoistEither
-- | Case analysis of a pair of monoid values returned by a monad into
-- a EitherT value.
-- The value conversion is done by @'pairToEither''@.
mPairToEitherT'
:: (Eq b, Monoid b, Functor m, Monad m)
=> m (b,a)
-> EitherT a m b
mPairToEitherT' pF = pairToEither' <$> lift pF >>= hoistEither
-- | Case analysis of a pair of monoid values returned by a monad into
-- a EitherT value.
-- The value conversion is done by @'pairBothToEither'@.
mPairBothToEitherT
:: (Eq a, Monoid a, Functor m, Monad m)
=> b
-> m (a,a)
-> EitherT b m a
mPairBothToEitherT def pF = pairBothToEither def <$> lift pF >>= hoistEither
-- | Transform a monoid value encapsulated in a @Monad m@ into the equivalent
-- EitherT e m monad transformer (@'mempty'@ -> @'Nothing'@).
mMonoidToEitherT :: (Eq a, Monoid a, Functor m, Monad m)
=> b
-> m a
-> EitherT b m a
mMonoidToEitherT def oF = monoidToEither def <$> lift oF >>= hoistEither
-- | Shorter alias for 'mMonoidToEitherT'
mOToET :: (Eq a, Monoid a, Functor m, Monad m)
=> b
-> m a
-> EitherT b m a
mOToET = mMonoidToEitherT
-- | Transform a boolean value encapsulated in a @Monad m@ into the equivalent
-- Either m monad transformer. Uses @'boolToEither'@.
mBoolToEitherT
:: (Functor m, Monad m)
=> b
-> a
-> m Bool
-> EitherT b m a
mBoolToEitherT l r bF = boolToEither l r <$> lift bF >>= hoistEither
-- | Shorter alias for @'mBoolToEitherT'@.
mBToET
:: (Functor m, Monad m)
=> b
-> a
-> m Bool
-> EitherT b m a
mBToET = mBoolToEitherT
-- | Change the left type using the provided conversion function.
-- This is a specialization of @'Control.Monad.Trans.Either.bimapEitherT'@.
--
-- > fmapLeftT f = bimapEitherT f id
--
-- or using the "errors" "Data.EitherR"
--
-- > fmapLeftT = fmapLT
fmapLeftT
:: Functor m
=> (a -> c)
-> EitherT a m b
-> EitherT c m b
fmapLeftT f = bimapEitherT f id
-- | Change the right type using the provided conversion function.
-- This is a specialization of @'Control.Monad.Trans.Either.bimapEitherT'@.
--
fmapRightT
:: Functor m
=> (b -> c)
-> EitherT a m b
-> EitherT a m c
fmapRightT = bimapEitherT id
-- This function executes an IO action that returns a monoid value, or raises
-- a @'IOException'@. If a @'IOException'@ is raised, or the return value
-- is an empty monoid, the function returns a left value in the
-- @EitherT IOException IO@ monad transformer. In the later case (empty monoid),
-- the exception will be of @'userErrorType'@ type, with the default string
-- \"empty monoid\". If you wish to specify your own message, see @'tryIOET''@.
--
-- /Note/: if a different type of exception is raised (@/= IOEXCEPTION@),
-- then that exception is re-thrown.
tryIOMonoidToEitherT
:: (Eq a, Monoid a)
=> IO a
-> EitherT IOException IO a
tryIOMonoidToEitherT ioF
= joinEitherMonoid (userError "empty monoid") <$> (lift . tryIOError) ioF
>>= hoistEither
-- | This function executes a IO action that returns a monoid value, or raises
-- an @'IOException'@. If a @'IOException'@ is raised, or the returned value
-- is an empty monoid, the function returns a left value in the
-- @EitherT IOException IO@ monad transformer. In the later case (empty monoid),
-- the exception will be of @'userErrorType'@ type, with the provided string
-- text.
tryIOET'
:: (Eq a, Monoid a)
=> String
-> IO a
-> EitherT IOException IO a
tryIOET' err ioF
= joinEitherMonoid (userError err) <$> (lift . tryIOError) ioF
>>= hoistEither
-- | This function executes a IO action that could raise an @'IOException'@.
-- If a @'IOException'@ is raised, the function returns a left value in the
-- @EitherT IOException IO@ monad transformer.
tryIOET :: IO a -> EitherT IOException IO a
tryIOET ioF = (lift . tryIOError) ioF >>= hoistEither