packages feed

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 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)