can-i-haz 0.2.1.0 → 0.3.0.0
raw patch · 5 files changed
+78/−9 lines, 5 filesdep +mtlPVP ok
version bump matches the API change (PVP)
Dependencies added: mtl
API changes (from Hackage documentation)
+ Control.Monad.Except.CoHas: (<$!>) :: Monad m => (a -> b) -> m a -> m b
+ Control.Monad.Except.CoHas: (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
+ Control.Monad.Except.CoHas: (=<<) :: Monad m => (a -> m b) -> m a -> m b
+ Control.Monad.Except.CoHas: (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
+ Control.Monad.Except.CoHas: (>>) :: Monad m => m a -> m b -> m b
+ Control.Monad.Except.CoHas: (>>=) :: Monad m => m a -> (a -> m b) -> m b
+ Control.Monad.Except.CoHas: ExceptT :: m (Either e a) -> ExceptT e a
+ Control.Monad.Except.CoHas: ap :: Monad m => m (a -> b) -> m a -> m b
+ Control.Monad.Except.CoHas: catchError :: MonadError e m => m a -> (e -> m a) -> m a
+ Control.Monad.Except.CoHas: class Functor (f :: Type -> Type)
+ Control.Monad.Except.CoHas: class Applicative m => Monad (m :: Type -> Type)
+ Control.Monad.Except.CoHas: class Monad m => MonadError e (m :: Type -> Type) | m -> e
+ Control.Monad.Except.CoHas: class Monad m => MonadFix (m :: Type -> Type)
+ Control.Monad.Except.CoHas: class Monad m => MonadIO (m :: Type -> Type)
+ Control.Monad.Except.CoHas: class (Alternative m, Monad m) => MonadPlus (m :: Type -> Type)
+ Control.Monad.Except.CoHas: class MonadTrans (t :: Type -> Type -> Type -> Type)
+ Control.Monad.Except.CoHas: fail :: Monad m => String -> m a
+ Control.Monad.Except.CoHas: filterM :: Applicative m => (a -> m Bool) -> [a] -> m [a]
+ Control.Monad.Except.CoHas: fix :: () => (a -> a) -> a
+ Control.Monad.Except.CoHas: fmap :: Functor f => (a -> b) -> f a -> f b
+ Control.Monad.Except.CoHas: foldM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
+ Control.Monad.Except.CoHas: foldM_ :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m ()
+ Control.Monad.Except.CoHas: forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)
+ Control.Monad.Except.CoHas: forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()
+ Control.Monad.Except.CoHas: forever :: Applicative f => f a -> f b
+ Control.Monad.Except.CoHas: guard :: Alternative f => Bool -> f ()
+ Control.Monad.Except.CoHas: infixl 1 >>
+ Control.Monad.Except.CoHas: infixl 4 <$!>
+ Control.Monad.Except.CoHas: infixr 1 =<<
+ Control.Monad.Except.CoHas: join :: Monad m => m (m a) -> m a
+ Control.Monad.Except.CoHas: lift :: (MonadTrans t, Monad m) => m a -> t m a
+ Control.Monad.Except.CoHas: liftEither :: (MonadError error m, CoHas option error) => Either option a -> m a
+ Control.Monad.Except.CoHas: liftIO :: MonadIO m => IO a -> m a
+ Control.Monad.Except.CoHas: liftM :: Monad m => (a1 -> r) -> m a1 -> m r
+ Control.Monad.Except.CoHas: liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
+ Control.Monad.Except.CoHas: liftM3 :: Monad m => (a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
+ Control.Monad.Except.CoHas: liftM4 :: Monad m => (a1 -> a2 -> a3 -> a4 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m r
+ Control.Monad.Except.CoHas: liftM5 :: Monad m => (a1 -> a2 -> a3 -> a4 -> a5 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m a5 -> m r
+ Control.Monad.Except.CoHas: mapAndUnzipM :: Applicative m => (a -> m (b, c)) -> [a] -> m ([b], [c])
+ Control.Monad.Except.CoHas: mapExcept :: () => (Either e a -> Either e' b) -> Except e a -> Except e' b
+ Control.Monad.Except.CoHas: mapExceptT :: () => (m (Either e a) -> n (Either e' b)) -> ExceptT e m a -> ExceptT e' n b
+ Control.Monad.Except.CoHas: mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)
+ Control.Monad.Except.CoHas: mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()
+ Control.Monad.Except.CoHas: mfilter :: MonadPlus m => (a -> Bool) -> m a -> m a
+ Control.Monad.Except.CoHas: mfix :: MonadFix m => (a -> m a) -> m a
+ Control.Monad.Except.CoHas: mplus :: MonadPlus m => m a -> m a -> m a
+ Control.Monad.Except.CoHas: msum :: (Foldable t, MonadPlus m) => t (m a) -> m a
+ Control.Monad.Except.CoHas: mzero :: MonadPlus m => m a
+ Control.Monad.Except.CoHas: newtype ExceptT e (m :: Type -> Type) a
+ Control.Monad.Except.CoHas: replicateM :: Applicative m => Int -> m a -> m [a]
+ Control.Monad.Except.CoHas: replicateM_ :: Applicative m => Int -> m a -> m ()
+ Control.Monad.Except.CoHas: return :: Monad m => a -> m a
+ Control.Monad.Except.CoHas: runExcept :: () => Except e a -> Either e a
+ Control.Monad.Except.CoHas: runExceptT :: () => ExceptT e m a -> m (Either e a)
+ Control.Monad.Except.CoHas: sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)
+ Control.Monad.Except.CoHas: sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()
+ Control.Monad.Except.CoHas: throwError :: (MonadError error m, CoHas option error) => option -> m a
+ Control.Monad.Except.CoHas: type Except e = ExceptT e Identity
+ Control.Monad.Except.CoHas: unless :: Applicative f => Bool -> f () -> f ()
+ Control.Monad.Except.CoHas: void :: Functor f => f a -> f ()
+ Control.Monad.Except.CoHas: when :: Applicative f => Bool -> f () -> f ()
+ Control.Monad.Except.CoHas: withExcept :: () => (e -> e') -> Except e a -> Except e' a
+ Control.Monad.Except.CoHas: withExceptT :: Functor m => (e -> e') -> ExceptT e m a -> ExceptT e' m a
+ Control.Monad.Except.CoHas: zipWithM :: Applicative m => (a -> b -> m c) -> [a] -> [b] -> m [c]
+ Control.Monad.Except.CoHas: zipWithM_ :: Applicative m => (a -> b -> m c) -> [a] -> [b] -> m ()
+ Control.Monad.Reader.Has: (<$!>) :: Monad m => (a -> b) -> m a -> m b
+ Control.Monad.Reader.Has: (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
+ Control.Monad.Reader.Has: (=<<) :: Monad m => (a -> m b) -> m a -> m b
+ Control.Monad.Reader.Has: (>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
+ Control.Monad.Reader.Has: (>>) :: Monad m => m a -> m b -> m b
+ Control.Monad.Reader.Has: (>>=) :: Monad m => m a -> (a -> m b) -> m b
+ Control.Monad.Reader.Has: ReaderT :: (r -> m a) -> ReaderT r
+ Control.Monad.Reader.Has: [runReaderT] :: ReaderT r -> r -> m a
+ Control.Monad.Reader.Has: ap :: Monad m => m (a -> b) -> m a -> m b
+ Control.Monad.Reader.Has: ask :: (MonadReader record m, Has part record) => m part
+ Control.Monad.Reader.Has: asks :: (MonadReader record m, Has part record) => (part -> a) -> m a
+ Control.Monad.Reader.Has: class Functor (f :: Type -> Type)
+ Control.Monad.Reader.Has: class Applicative m => Monad (m :: Type -> Type)
+ Control.Monad.Reader.Has: class Monad m => MonadFix (m :: Type -> Type)
+ Control.Monad.Reader.Has: class Monad m => MonadIO (m :: Type -> Type)
+ Control.Monad.Reader.Has: class (Alternative m, Monad m) => MonadPlus (m :: Type -> Type)
+ Control.Monad.Reader.Has: class Monad m => MonadReader r (m :: Type -> Type) | m -> r
+ Control.Monad.Reader.Has: class MonadTrans (t :: Type -> Type -> Type -> Type)
+ Control.Monad.Reader.Has: fail :: Monad m => String -> m a
+ Control.Monad.Reader.Has: filterM :: Applicative m => (a -> m Bool) -> [a] -> m [a]
+ Control.Monad.Reader.Has: fix :: () => (a -> a) -> a
+ Control.Monad.Reader.Has: fmap :: Functor f => (a -> b) -> f a -> f b
+ Control.Monad.Reader.Has: foldM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
+ Control.Monad.Reader.Has: foldM_ :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m ()
+ Control.Monad.Reader.Has: forM :: (Traversable t, Monad m) => t a -> (a -> m b) -> m (t b)
+ Control.Monad.Reader.Has: forM_ :: (Foldable t, Monad m) => t a -> (a -> m b) -> m ()
+ Control.Monad.Reader.Has: forever :: Applicative f => f a -> f b
+ Control.Monad.Reader.Has: guard :: Alternative f => Bool -> f ()
+ Control.Monad.Reader.Has: infixl 1 >>
+ Control.Monad.Reader.Has: infixl 4 <$!>
+ Control.Monad.Reader.Has: infixr 1 =<<
+ Control.Monad.Reader.Has: join :: Monad m => m (m a) -> m a
+ Control.Monad.Reader.Has: lift :: (MonadTrans t, Monad m) => m a -> t m a
+ Control.Monad.Reader.Has: liftIO :: MonadIO m => IO a -> m a
+ Control.Monad.Reader.Has: liftM :: Monad m => (a1 -> r) -> m a1 -> m r
+ Control.Monad.Reader.Has: liftM2 :: Monad m => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
+ Control.Monad.Reader.Has: liftM3 :: Monad m => (a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
+ Control.Monad.Reader.Has: liftM4 :: Monad m => (a1 -> a2 -> a3 -> a4 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m r
+ Control.Monad.Reader.Has: liftM5 :: Monad m => (a1 -> a2 -> a3 -> a4 -> a5 -> r) -> m a1 -> m a2 -> m a3 -> m a4 -> m a5 -> m r
+ Control.Monad.Reader.Has: local :: MonadReader r m => (r -> r) -> m a -> m a
+ Control.Monad.Reader.Has: mapAndUnzipM :: Applicative m => (a -> m (b, c)) -> [a] -> m ([b], [c])
+ Control.Monad.Reader.Has: mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)
+ Control.Monad.Reader.Has: mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()
+ Control.Monad.Reader.Has: mapReader :: () => (a -> b) -> Reader r a -> Reader r b
+ Control.Monad.Reader.Has: mapReaderT :: () => (m a -> n b) -> ReaderT r m a -> ReaderT r n b
+ Control.Monad.Reader.Has: mfilter :: MonadPlus m => (a -> Bool) -> m a -> m a
+ Control.Monad.Reader.Has: mfix :: MonadFix m => (a -> m a) -> m a
+ Control.Monad.Reader.Has: mplus :: MonadPlus m => m a -> m a -> m a
+ Control.Monad.Reader.Has: msum :: (Foldable t, MonadPlus m) => t (m a) -> m a
+ Control.Monad.Reader.Has: mzero :: MonadPlus m => m a
+ Control.Monad.Reader.Has: newtype ReaderT r (m :: k -> Type) (a :: k) :: forall k. () => Type -> k -> Type -> k -> Type
+ Control.Monad.Reader.Has: reader :: (MonadReader record m, Has part record) => (part -> a) -> m a
+ Control.Monad.Reader.Has: replicateM :: Applicative m => Int -> m a -> m [a]
+ Control.Monad.Reader.Has: replicateM_ :: Applicative m => Int -> m a -> m ()
+ Control.Monad.Reader.Has: return :: Monad m => a -> m a
+ Control.Monad.Reader.Has: runReader :: () => Reader r a -> r -> a
+ Control.Monad.Reader.Has: sequence :: (Traversable t, Monad m) => t (m a) -> m (t a)
+ Control.Monad.Reader.Has: sequence_ :: (Foldable t, Monad m) => t (m a) -> m ()
+ Control.Monad.Reader.Has: type Reader r = ReaderT r Identity
+ Control.Monad.Reader.Has: unless :: Applicative f => Bool -> f () -> f ()
+ Control.Monad.Reader.Has: void :: Functor f => f a -> f ()
+ Control.Monad.Reader.Has: when :: Applicative f => Bool -> f () -> f ()
+ Control.Monad.Reader.Has: withReader :: () => (r' -> r) -> Reader r a -> Reader r' a
+ Control.Monad.Reader.Has: withReaderT :: () => (r' -> r) -> ReaderT r m a -> ReaderT r' m a
+ Control.Monad.Reader.Has: zipWithM :: Applicative m => (a -> b -> m c) -> [a] -> [b] -> m [c]
+ Control.Monad.Reader.Has: zipWithM_ :: Applicative m => (a -> b -> m c) -> [a] -> [b] -> m ()
Files
- ChangeLog.md +6/−0
- README.md +2/−1
- can-i-haz.cabal +4/−2
- src/Control/Monad/Except/CoHas.hs +28/−2
- src/Control/Monad/Reader/Has.hs +38/−4
ChangeLog.md view
@@ -1,5 +1,11 @@ # Changelog for can-i-haz +## 0.3.0.0++* Reexport `Control.Monad.Reader` from the `Control.Monad.Reader.Has` module with+ custom `ask`, `asks` and `reader` functions more compatible with the `Has` class.+* Similarly for `Control.Monad.Except`, `CoHas` and `throwError`/`liftError` functions.+ ## 0.2.1.0 * Added the `update` method to `Has` (yay lenses).
README.md view
@@ -5,7 +5,8 @@ [![Stackage LTS][stackage-lts-badge]][stackage-lts] [![Stackage Nightly][stackage-nightly-badge]][stackage-nightly] -`Generic` implementation of the Has-pattern (mostly useful with `MonadReader`).+`Generic` implementation of the Has-pattern (mostly useful with `MonadReader` and `MonadState`)+and its dual `CoHas` (mostly useful with `MonadError`). ## Motivation
can-i-haz.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 92db1c8cf04877be4feda903d215b85919cb662aadcc285eb2f2e6e05f660886+-- hash: c910611bf208cea23fae88a3630f1682ec77f54fcef2a2aed6b14ef41a12904c name: can-i-haz-version: 0.2.1.0+version: 0.3.0.0 synopsis: Generic implementation of the Has and CoHas patterns description: Please see the README on GitHub at <https://github.com/0xd34df00d/can-i-haz#readme> category: Control@@ -39,6 +39,7 @@ ghc-options: -Wall build-depends: base >=4.7 && <5+ , mtl default-language: Haskell2010 test-suite can-i-haz-test@@ -57,4 +58,5 @@ , can-i-haz , deepseq , hspec+ , mtl default-language: Haskell2010
src/Control/Monad/Except/CoHas.hs view
@@ -7,8 +7,8 @@ Description: Generic implementation of the CoHas injection pattern (dual to Has) Stability: experimental -This module defines a class 'CoHas' intended to be used with the 'Control.Monad.Except.MonadError' class-(and similar ones) or 'Control.Monad.Except.Except'/'Control.Monad.ExceptT' types.+This module defines a class 'CoHas' intended to be used with the 'MonadError' class+(and similar ones) or 'Except' / 'ExceptT' types. = The problem @@ -70,13 +70,25 @@ we instead decide that such a choice is inherently ambiguous, so this library will refuse to generate an instance in this case as well. += Exports++This module also reexports 'Control.Monad.Except' along with some functions like 'throwError' or 'liftEither'+with types adjusted for the intended usage of the 'CoHas' class.+ -} module Control.Monad.Except.CoHas ( CoHas(..) , SuccessfulSearch++, module X+, throwError+, liftEither ) where +import qualified Control.Monad.Except as M+import Control.Monad.Except as X hiding(throwError, liftEither)+import Data.Bifunctor import Data.Proxy import GHC.Generics @@ -126,3 +138,17 @@ inject = id instance SuccessfulSearch a (Either l r) path => CoHas a (Either l r)++-- | Begin error processing for the error of type @option@.+--+-- This is "Control.Monad.Except"'s 'Control.Monad.Except.throwError'+-- with the type adjusted for better compatibility with 'CoHas'.+throwError :: (MonadError error m, CoHas option error) => option -> m a+throwError = M.throwError . inject++-- | Lifts an 'Either' @option@ into any 'MonadError' @error@ where @option@ can be 'inject'ed into @error@.+--+-- This is "Control.Monad.Except"'s 'Control.Monad.Except.liftEither'+-- with the type adjusted for better compatibility with 'CoHas'.+liftEither :: (MonadError error m, CoHas option error) => Either option a -> m a+liftEither = M.liftEither . first inject
src/Control/Monad/Reader/Has.hs view
@@ -7,12 +7,12 @@ Description : Generic implementation of the Has pattern Stability : experimental -This module defines a class 'Has' intended to be used with the 'Control.Monad.Reader.MonadReader' class-or 'Control.Monad.Reader.Reader' / 'Control.Monad.Reader.ReaderT' types.+This module defines a class 'Has' intended to be used with the 'MonadReader' class+or 'Reader' / 'ReaderT' types. = The problem -Assume there are two types representing the 'Control.Monad.Reader.MonadReader' environments+Assume there are two types representing the 'MonadReader' environments for different parts of an application: @@@ -80,15 +80,28 @@ Note that this might be used for more composable functions living in 'Control.Monad.State': now instead of @MonadState StateType m@ we write @(MonadState s m, Has StateType s)@-and use 'update' and 'extract' where necessary (likely in combination with 'modify' and 'gets').+and use 'update' and 'extract' where necessary+(likely in combination with 'Control.Monad.State.modify' and 'Control.Monad.State.gets'). += Exports++This module also reexports 'Control.Monad.Reader' along with some functions like 'ask' or 'reader'+with types adjusted for the intended usage of the 'Has' class.+ -} module Control.Monad.Reader.Has ( Has(..) , SuccessfulSearch++, module X+, ask+, asks+, reader ) where +import qualified Control.Monad.Reader as M+import Control.Monad.Reader as X hiding(ask, asks, reader) import Data.Proxy import GHC.Generics @@ -159,3 +172,24 @@ instance SuccessfulSearch a (a0, a1, a2, a3) path => Has a (a0, a1, a2, a3) instance SuccessfulSearch a (a0, a1, a2, a3, a4) path => Has a (a0, a1, a2, a3, a4) instance SuccessfulSearch a (a0, a1, a2, a3, a4, a5) path => Has a (a0, a1, a2, a3, a4, a5)++-- | Retrieves the @part@ of the monad environment.+--+-- This is "Control.Monad.Reader"'s 'Control.Monad.Reader.ask'+-- with the type adjusted for better compatibility with 'Has'.+ask :: (MonadReader record m, Has part record) => m part+ask = M.asks extract++-- | Retrieves a function of the @part@ of the current environment.+--+-- This is "Control.Monad.Reader"'s 'Control.Monad.Reader.asks'+-- with the type adjusted for better compatibility with 'Has'.+asks :: (MonadReader record m, Has part record) => (part -> a) -> m a+asks f = f <$> ask++-- | Retrieves a function of the @part@ of the current environment.+--+-- This is "Control.Monad.Reader"'s 'Control.Monad.Reader.reader'+-- with the type adjusted for better compatibility with 'Has'.+reader :: (MonadReader record m, Has part record) => (part -> a) -> m a+reader = asks