simple-effects 0.5.0.1 → 0.5.0.2
raw patch · 7 files changed
+29/−26 lines, 7 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Control.Effects.State: handleSubstate :: MonadEffectState s m => Lens' s t -> t -> EffectHandlerState t m a -> m a
+ Control.Effects.Signal: handleException :: Monad m => (a -> m c) -> ExceptT a m c -> m c
+ Control.Effects.Signal: handleToEither :: ExceptT e m a -> m (Either e a)
+ Control.Effects.Signal: instance GHC.Base.Monad m => Control.Effects.MonadEffect (Control.Effects.Signal.Signal e b) (Control.Monad.Trans.Except.ExceptT e m)
+ Control.Effects.Signal: instance GHC.Base.Monad m => Control.Effects.Signal.MonadEffectSignal e Data.Void.Void (Control.Monad.Trans.Except.ExceptT e m)
- Control.Effects: handleEffect :: Monad m => (EffectMsg eff -> m (EffectRes eff)) -> EffectHandler eff m a -> m a
+ Control.Effects: handleEffect :: (EffectMsg eff -> m (EffectRes eff)) -> EffectHandler eff m a -> m a
- Control.Effects.Reader: handleReadEnv :: Monad m => m e -> EffectHandler (ReadEnv e) m a -> m a
+ Control.Effects.Reader: handleReadEnv :: m e -> EffectHandler (ReadEnv e) m a -> m a
- Control.Effects.State: handleGetState :: Monad m => m s -> EffectHandler (GetState s) m a -> m a
+ Control.Effects.State: handleGetState :: m s -> EffectHandler (GetState s) m a -> m a
- Control.Effects.State: handleSetState :: Monad m => (s -> m ()) -> EffectHandler (SetState s) m a -> m a
+ Control.Effects.State: handleSetState :: (s -> m ()) -> EffectHandler (SetState s) m a -> m a
- Control.Effects1: handleEffect1 :: Monad m => (forall a. EffectCon1 eff a => EffectMsg1 eff a -> m (EffectRes1 eff a)) -> EffectHandler1 eff m a -> m a
+ Control.Effects1: handleEffect1 :: (forall a. EffectCon1 eff a => EffectMsg1 eff a -> m (EffectRes1 eff a)) -> EffectHandler1 eff m b -> m b
Files
- simple-effects.cabal +2/−1
- src/Control/Effects.hs +2/−2
- src/Control/Effects/Early.hs +0/−1
- src/Control/Effects/Reader.hs +1/−3
- src/Control/Effects/Signal.hs +19/−2
- src/Control/Effects/State.hs +2/−14
- src/Control/Effects1.hs +3/−3
simple-effects.cabal view
@@ -1,5 +1,5 @@ name: simple-effects -version: 0.5.0.1 +version: 0.5.0.2 synopsis: A simple effect system that integrates with MTL description: Please see README.md homepage: https://gitlab.com/LukaHorvat/simple-effects @@ -31,6 +31,7 @@ , list-t , lens default-extensions: NoImplicitPrelude + ghc-options: -Wall benchmark bench-effects type: exitcode-stdio-1.0
src/Control/Effects.hs view
@@ -3,7 +3,7 @@ , IncoherentInstances #-} module Control.Effects (module Control.Effects, module Control.Effects1) where -import Interlude +import Interlude hiding (msg) import Control.Monad.Reader import Control.Monad.Trans.Control @@ -48,5 +48,5 @@ effect _ msg = EffectHandler (ReaderT ($ msg)) -- | Handle the effect described by 'eff'. -handleEffect :: Monad m => (EffectMsg eff -> m (EffectRes eff)) -> EffectHandler eff m a -> m a +handleEffect :: (EffectMsg eff -> m (EffectRes eff)) -> EffectHandler eff m a -> m a handleEffect f eh = runReaderT (unpackEffectHandler eh) f
src/Control/Effects/Early.hs view
@@ -2,7 +2,6 @@ module Control.Effects.Early (module Control.Effects, Early, earlyReturn, handleEarly) where import Interlude -import Prelude (Show(..)) import Control.Monad.Trans.Except import Control.Effects
src/Control/Effects/Reader.hs view
@@ -3,8 +3,6 @@ import Interlude -import Control.Lens - import Control.Effects data ReadEnv e @@ -15,7 +13,7 @@ readEnv :: forall m e. MonadEffect (ReadEnv e) m => m e readEnv = effect (Proxy :: Proxy (ReadEnv e)) () -handleReadEnv :: Monad m => m e -> EffectHandler (ReadEnv e) m a -> m a +handleReadEnv :: m e -> EffectHandler (ReadEnv e) m a -> m a handleReadEnv = handleEffect . const handleSubreader :: MonadEffect (ReadEnv e) m => (e -> e') -> EffectHandler (ReadEnv e') m a -> m a
src/Control/Effects/Signal.hs view
@@ -3,10 +3,9 @@ {-# LANGUAGE FlexibleInstances, UndecidableInstances #-} module Control.Effects.Signal ( MonadEffectSignal(..), ResumeOrBreak(..), throwSignal, handleSignal, handleAsException - , Throws, module Control.Effects ) where + , Throws, handleException, handleToEither, module Control.Effects ) where import Interlude -import Prelude (Show(..)) import Control.Monad.Trans.Except import Control.Effects @@ -15,6 +14,9 @@ type instance EffectMsg (Signal a b) = a type instance EffectRes (Signal a b) = b +instance Monad m => MonadEffect (Signal e b) (ExceptT e m) where + effect _ = throwE + -- | This class allows you to "throw" a signal. For the most part signals are the same as checked -- exceptions. The difference here is that the handler has the option to provide the value that -- will be the result _of calling the signal function_. This effectibvely allows you to have @@ -30,6 +32,7 @@ type Throws e m = MonadEffectSignal e Void m instance Monad m => MonadEffectSignal a b (EffectHandler (Signal a b) m) +instance Monad m => MonadEffectSignal e Void (ExceptT e m) instance {-# OVERLAPPABLE #-} (MonadEffectSignal a b m, MonadTrans t, Monad (t m)) => MonadEffectSignal a b (t m) @@ -72,3 +75,17 @@ -> EffectHandler (Signal a b) (ExceptT c m) c -> m c handleAsException f = handleSignal (fmap Break . f) + +-- | In case only 'throwSignal' is used then the function signatures will have a @'Throws' a m@ +-- constraint or, equivalently, a @'MonadEffectSignal' a Void m@ constraint. In those cases you +-- can use this function to handle their exceptions. This function will not work for handing other +-- signals because 'ExceptT' doesn't satisfy other constraints. +-- +-- The advantage of using this handler is that your inferred transformer stack will have one less +-- layer which can potentially lead to slight performance increases. +handleException :: Monad m => (a -> m c) -> ExceptT a m c -> m c +handleException f = either f return <=< runExceptT + +-- | See documentation for 'handleException'. This handler gives you an 'Either'. +handleToEither :: ExceptT e m a -> m (Either e a) +handleToEither = runExceptT
src/Control/Effects/State.hs view
@@ -5,7 +5,6 @@ import Interlude import Data.IORef -import Control.Lens import Control.Effects @@ -39,11 +38,11 @@ {-# INLINE modifyState #-} modifyState f = setState . f =<< getState -handleGetState :: Monad m => m s -> EffectHandler (GetState s) m a -> m a +handleGetState :: m s -> EffectHandler (GetState s) m a -> m a {-# INLINE handleGetState #-} handleGetState = handleEffect . const -handleSetState :: Monad m => (s -> m ()) -> EffectHandler (SetState s) m a -> m a +handleSetState :: (s -> m ()) -> EffectHandler (SetState s) m a -> m a {-# INLINE handleSetState #-} handleSetState = handleEffect @@ -60,14 +59,3 @@ handleStateT :: Monad m => s -> StateT s m a -> m a {-# INLINE handleStateT #-} handleStateT = flip evalStateT - -handleSubstate :: MonadEffectState s m => Lens' s t -> t -> EffectHandlerState t m a -> m a -handleSubstate lensST initial m = do - oldState <- getState - setState (set lensST initial oldState) - res <- m & handleGetState (view lensST <$> getState) - & handleSetState (\s -> do - oldState <- getState - setState (oldState & lensST .~ s)) - setState oldState - return res
src/Control/Effects1.hs view
@@ -3,7 +3,7 @@ , IncoherentInstances, RankNTypes, ConstraintKinds #-} module Control.Effects1 where -import Interlude +import Interlude hiding (msg) import Control.Monad.Reader import Control.Monad.Trans.Control @@ -48,6 +48,6 @@ effect1 _ msg = EffectHandler1 (ReaderT (($ msg) . getHandling1)) -- | Handle the effect described by 'eff'. -handleEffect1 :: Monad m => (forall a. EffectCon1 eff a => EffectMsg1 eff a -> m (EffectRes1 eff a)) - -> EffectHandler1 eff m a -> m a +handleEffect1 :: (forall a. EffectCon1 eff a => EffectMsg1 eff a -> m (EffectRes1 eff a)) + -> EffectHandler1 eff m b -> m b handleEffect1 f eh = runReaderT (unpackEffectHandler1 eh) (EffHandling1 f)