transformers-convert (empty) → 0.2.0.0
raw patch · 5 files changed
+477/−0 lines, 5 filesdep +HUnitdep +QuickCheckdep +basesetup-changed
Dependencies added: HUnit, QuickCheck, base, data-easy, directory, either, errors, haskell-src-exts, hlint, hspec, text, transformers, unix
Files
- LICENSE +30/−0
- Setup.hs +2/−0
- src/Control/Monad/Trans/Convert.hs +378/−0
- test/main.hs +10/−0
- transformers-convert.cabal +57/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2013, João Cristóvão++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of João Cristóvão nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Control/Monad/Trans/Convert.hs view
@@ -0,0 +1,378 @@+{-# 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++
+ test/main.hs view
@@ -0,0 +1,10 @@+{-# LANGUAGE CPP #-}++import Test.Hspec++import qualified CMTCTest as CMTCT++main :: IO ()+main = hspec $ do+ CMTCT.specs+
+ transformers-convert.cabal view
@@ -0,0 +1,57 @@+name: transformers-convert+version: 0.2.0.0+synopsis: Sensible conversions between some of the monad transformers+description: Sensible conversions between MaybeT and EitherT monad transformers. +homepage: https://github.com/jcristovao/transformers-convert+license: BSD3+license-file: LICENSE+author: João Cristóvão+maintainer: jmacristovao@gmail.com+category: Control+build-type: Simple++-- Extra files to be distributed with the package, such as examples or a README.+-- extra-source-files: ++-- Constraint on the version of Cabal needed to build this package.+cabal-version: >=1.18+++library+ exposed-modules: Control.Monad.Trans.Convert ++ -- Modules included in this library but not exported.+ -- other-modules: + + -- Other library packages from which modules are imported.+ build-depends: base >= 4.6 && < 5+ , transformers >= 0.3 && < 0.5+ , either >= 4.0 && < 4.2+ , data-easy >= 0.4 && < 0.5+ + -- Directories containing source files.+ hs-source-dirs: src + + -- Base language which the package is written in.+ default-language: Haskell2010++ ghc-options: -Wall+ +test-suite test+ type: exitcode-stdio-1.0+ main-is: main.hs+ hs-source-dirs: test, src+ build-depends: base >= 4.6 && < 5+ , transformers >= 0.3 && < 0.5+ , either >= 4.1.1 && < 4.2+ , data-easy >= 0.4 && < 0.5+ , text >= 0.11.3 + , errors >= 1.4.3 && < 1.5+ , directory >= 1.2.0.1 && < 1.3+ , QuickCheck >= 2.6 + , HUnit >= 1.2.5.2+ , hspec >= 1.7.2+ , unix >= 2.6+ , haskell-src-exts >= 1.14+ , hlint+ default-language : Haskell2010