extensible-effects 2.2.1.0 → 2.3.0.0
raw patch · 14 files changed
+77/−69 lines, 14 filesdep −type-alignedPVP ok
version bump matches the API change (PVP)
Dependencies removed: type-aligned
API changes (from Hackage documentation)
- Control.Eff.Exception: catchExc :: Member (Exc e) r => Eff r a -> (e -> Eff r a) -> Eff r a
- Control.Eff.Exception: rethrowExc :: (Member (Exc e') r) => (e -> e') -> Eff (Exc e : r) a -> Eff r a
- Control.Eff.Exception: runExc :: Eff (Exc e : r) a -> Eff r (Either e a)
- Control.Eff.Exception: throwExc :: (Member (Exc e) r) => e -> Eff r a
- Control.Eff.State.Strict: ProxyState :: ProxyState s
- Control.Eff.State.Strict: data ProxyState s
+ Control.Eff.Exception: catchError :: Member (Exc e) r => Eff r a -> (e -> Eff r a) -> Eff r a
+ Control.Eff.Exception: rethrowError :: (Member (Exc e') r) => (e -> e') -> Eff (Exc e : r) a -> Eff r a
+ Control.Eff.Exception: runError :: Eff (Exc e : r) a -> Eff r (Either e a)
+ Control.Eff.Exception: throwError :: (Member (Exc e) r) => e -> Eff r a
+ Control.Eff.State.Strict: TxState :: TxState s
+ Control.Eff.State.Strict: data TxState s
+ Data.OpenUnion: instance t ~ s => Data.OpenUnion.FindElem t '[s]
+ Data.OpenUnion: instance t ~ s => Data.OpenUnion.Member t '[s]
- Control.Eff.State.Strict: transactionState :: forall s r w. Member (State s) r => ProxyState s -> Eff r w -> Eff r w
+ Control.Eff.State.Strict: transactionState :: forall s r w. Member (State s) r => TxState s -> Eff r w -> Eff r w
Files
- README.md +10/−3
- benchmark/Benchmarks.hs +5/−5
- extensible-effects.cabal +2/−3
- src/Control/Eff/Cut.hs +1/−1
- src/Control/Eff/Example.hs +3/−3
- src/Control/Eff/Exception.hs +16/−16
- src/Control/Eff/State/Strict.hs +2/−2
- src/Data/OpenUnion.hs +7/−5
- test/Control/Eff/Choose/Test.hs +2/−2
- test/Control/Eff/Example/Test.hs +1/−1
- test/Control/Eff/Exception/Test.hs +12/−12
- test/Control/Eff/Lift/Test.hs +7/−7
- test/Control/Eff/State/LazyState/Test.hs +3/−3
- test/Control/Eff/State/Strict/Test.hs +6/−6
README.md view
@@ -24,9 +24,16 @@ ## Disadvantages ### Ambiguity-Flexibility tradeoff- * The extensibility comes at the cost of some ambiguity. Note, however, that- the extensibility can be traded back, but that detracts from some of the- advantages. For details see section 4.1 in the++A useful pattern to manage the ambiguity-flexibility tradeoff is to specialize+the call to the handler of effects using+[type application](https://ghc.haskell.org/trac/ghc/wiki/TypeApplication) or+type annotation. Examples of this pattern can be seen in+[Example/Test.hs](./test/Control/Eff/Example/Test.hs).++ * The extensibility of `Eff` comes at the cost of some ambiguity. Note,+ however, that the extensibility can be traded back, but that detracts from+ some of the advantages. For details see section 4.1 in the [paper](http://okmij.org/ftp/Haskell/extensible/exteff.pdf). This issue manifests itself in a few ways: * Common functions can't be grouped using typeclasses, e.g.
benchmark/Benchmarks.hs view
@@ -86,10 +86,10 @@ f acc x = return $! acc * x benchMul_Eff :: Int -> Int-benchMul_Eff n = either id id . run . runExc $ m+benchMul_Eff n = either id id . run . runError $ m where m = foldM f 1 (be_make_list n)- f acc 0 = E.Er.throwExc (0::Int)+ f acc 0 = E.Er.throwError (0::Int) f acc x = return $! acc * x -- ------------------------------------------------------------------------@@ -114,7 +114,7 @@ Int -> Eff r Int benchMax_Eff n = foldM f 1 [n, n-1 .. 0] where- f acc 0 = E.Er.throwExc (0::Int)+ f acc 0 = E.Er.throwError (0::Int) f acc x | x `mod` 5 == 0 = do s <- E.S.get E.S.put $! (s+1::Int)@@ -122,10 +122,10 @@ f acc x = return $! max acc x -mainMax_Eff n = ((run $ E.S.runState (E.Er.runExc (benchMax_Eff n)) 0) ::+mainMax_Eff n = ((run $ E.S.runState (E.Er.runError (benchMax_Eff n)) 0) :: (Either Int Int,Int)) -mainMax1_Eff n = ((run $ E.Er.runExc (E.S.runState (benchMax_Eff n) 0)) ::+mainMax1_Eff n = ((run $ E.Er.runError (E.S.runState (benchMax_Eff n) 0)) :: Either Int (Int,Int)) -- ------------------------------------------------------------------------
extensible-effects.cabal view
@@ -6,7 +6,7 @@ -- PVP summary: +-+------- breaking API changes -- | | +----- non-breaking API additions -- | | | +--- code changes with no API change-version: 2.2.1.0+version: 2.3.0.0 -- A short (one-line) description of the package. synopsis: An Alternative to Monad Transformers@@ -60,7 +60,7 @@ flag force-openunion-51 description: Force usage of OpenUnion51.hs implementation- default: True+ default: False manual: True library@@ -122,7 +122,6 @@ -- Other library packages from which modules are imported. build-depends: base >= 4.6 && < 5- , type-aligned >= 0.9.3 -- For MonadIO instance , transformers >= 0.3 && < 0.6 -- For MonadBase instance
src/Control/Eff/Cut.hs view
@@ -47,7 +47,7 @@ data CutFalse = CutFalse cutfalse :: Member (Exc CutFalse) r => Eff r a-cutfalse = throwExc CutFalse+cutfalse = throwError CutFalse -- | The interpreter -- it is like reify . reflect with a twist. Compare this -- implementation with the huge implementation of call in Hinze 2000 (Figure 9).
src/Control/Eff/Example.hs view
@@ -12,16 +12,16 @@ import Control.Eff.State.Lazy import Control.Eff.Writer.Lazy - -- {{{ TooBig+-- {{{ TooBig -- | The datatype for the example from the paper. See the tests for the example newtype TooBig = TooBig Int deriving (Eq, Show) -- | specialization to tell the type of the exception runErrBig :: Eff (Exc TooBig ': r) a -> Eff r (Either TooBig a)-runErrBig = runExc+runErrBig = runError - -- }}}+-- }}} -- | Write the elements of a list of numbers, in order. writeAll :: (Member (Writer a) e)
src/Control/Eff/Exception.hs view
@@ -7,13 +7,13 @@ -- | Exception-producing and exception-handling effects module Control.Eff.Exception ( Exc (..) , Fail- , throwExc+ , throwError , die- , runExc+ , runError , runFail- , catchExc+ , catchError , onFail- , rethrowExc+ , rethrowError , liftEither , liftEitherM , liftMaybe@@ -35,33 +35,33 @@ type Fail = Exc () -- | Throw an exception in an effectful computation. The type is inferred.-throwExc :: (Member (Exc e) r) => e -> Eff r a-throwExc e = send (Exc e)-{-# INLINE throwExc #-}+throwError :: (Member (Exc e) r) => e -> Eff r a+throwError e = send (Exc e)+{-# INLINE throwError #-} -- | Makes an effect fail, preventing future effects from happening. die :: Member Fail r => Eff r a-die = throwExc ()+die = throwError () {-# INLINE die #-} -- | Run a computation that might produce an exception.-runExc :: Eff (Exc e ': r) a -> Eff r (Either e a)-runExc = handle_relay+runError :: Eff (Exc e ': r) a -> Eff r (Either e a)+runError = handle_relay (return . Right) (\(Exc e) _k -> return (Left e)) -- | Runs a failable effect, such that failed computation return 'Nothing', and -- 'Just' the return value on success. runFail :: Eff (Fail ': r) a -> Eff r (Maybe a)-runFail = fmap (either (const Nothing) Just) . runExc+runFail = fmap (either (const Nothing) Just) . runError {-# INLINE runFail #-} -- | Run a computation that might produce exceptions, and give it a way to deal -- with the exceptions that come up. The handler is allowed to rethrow the -- exception-catchExc :: Member (Exc e) r =>+catchError :: Member (Exc e) r => Eff r a -> (e -> Eff r a) -> Eff r a-catchExc m handle = interpose return (\(Exc e) _k -> handle e) m+catchError m handle = interpose return (\(Exc e) _k -> handle e) m -- | Add a default value (i.e. failure handler) to a fallible computation. -- This hides the fact that a failure happened.@@ -73,15 +73,15 @@ -- | Run a computation until it produces an exception, -- and convert and throw that exception in a new context.-rethrowExc :: (Member (Exc e') r)+rethrowError :: (Member (Exc e') r) => (e -> e') -> Eff (Exc e ': r) a -> Eff r a-rethrowExc t eff = runExc eff >>= either (throwExc . t) return+rethrowError t eff = runError eff >>= either (throwError . t) return -- | Treat Lefts as exceptions and Rights as return values. liftEither :: (Member (Exc e) r) => Either e a -> Eff r a-liftEither = either throwExc return+liftEither = either throwError return {-# INLINE liftEither #-} -- | `liftEither` in a lifted Monad
src/Control/Eff/State/Strict.hs view
@@ -94,9 +94,9 @@ -- | An encapsulated State handler, for transactional semantics -- The global state is updated only if the transactionState finished -- successfully-data ProxyState s = ProxyState+data TxState s = TxState transactionState :: forall s r w. Member (State s) r =>- ProxyState s -> Eff r w -> Eff r w+ TxState s -> Eff r w -> Eff r w transactionState _ m = do s <- get; loop s m where loop :: s -> Eff r w -> Eff r w
src/Data/OpenUnion.hs view
@@ -151,17 +151,15 @@ class FindElem (t :: * -> *) r where elemNo :: P t r -#if __GLASGOW_HASKELL__ < 710 || FORCE_OU51-instance FindElem t (t ': r) where-#else+#if !(__GLASGOW_HASKELL__ < 710 || FORCE_OU51) -- Stopped Using Obsolete -XOverlappingInstances -- and explicitly specify to choose the topmost -- one for multiple occurence, which is the same -- behaviour as OpenUnion51 with GHC 7.10.-instance {-# INCOHERENT #-} t ~ s => FindElem t '[s] where+instance {-# INCOHERENT #-} t ~ s => FindElem t '[s] where elemNo = P 0-instance {-# INCOHERENT #-} FindElem t (t ': r) where #endif+instance FindElem t (t ': r) where elemNo = P 0 #if __GLASGOW_HASKELL__ < 710 || FORCE_OU51@@ -176,7 +174,11 @@ -- module class EQU (a :: k) (b :: k) p | a b -> p instance EQU a a 'True+#if __GLASGOW_HASKELL__ < 710 || FORCE_OU51 instance (p ~ 'False) => EQU a b p+#else+instance {-# OVERLAPPABLE #-} (p ~ 'False) => EQU a b p+#endif -- | This class is used for emulating monad transformers class Member t r => SetMember (tag :: k -> * -> *) (t :: * -> *) r | tag r -> t
test/Control/Eff/Choose/Test.hs view
@@ -52,6 +52,6 @@ -- The code is the same as in transf1.hs. The inferred signatures differ -- Was: exRec :: MonadError TooBig m => m Int -> m Int -- exRec :: Member (Exc TooBig) r => Eff r Int -> Eff r Int- exRec m = catchExc m handler+ exRec m = catchError m handler where handler (TooBig n) | n <= 7 = return n- handler e = throwExc e+ handler e = throwError e
test/Control/Eff/Example/Test.hs view
@@ -23,7 +23,7 @@ -- ex2 :: Member (Exc TooBig) r => Eff r Int -> Eff r Int ex2 m = do v <- m- if v > 5 then throwExc (TooBig v)+ if v > 5 then throwError (TooBig v) else return v case_Exception1_ex2r :: Assertion
test/Control/Eff/Exception/Test.hs view
@@ -26,7 +26,7 @@ -- The type is inferred -- et2 :: Member (Exc Int) r => Eff r Int-et2 = return 1 `add` throwExc (2::Int)+et2 = return 1 `add` throwError (2::Int) -- The following won't type: unhandled exception! -- ex2rw = run et2@@ -42,7 +42,7 @@ -- The inferred type shows that ex21 is now pure -- et21 :: Eff r (Either Int Int) - et21 = runExc et2+ et21 = runError et2 -- Implementing the operator <|> from Alternative: -- a <|> b does@@ -56,24 +56,24 @@ alttry :: forall e r a. (Monoid e, SetMember Exc (Exc e) r) => Eff r a -> Eff r a -> Eff r a alttry ma mb =- catchExc ma $ \ea ->- catchExc mb $ \eb -> throwExc (mappend (ea::e) eb)+ catchError ma $ \ea ->+ catchError mb $ \eb -> throwError (mappend (ea::e) eb) case_Exception1_alttry :: Assertion case_Exception1_alttry = [Right 10,Right 10,Right 10,Left "bummer1bummer2"] @=? [- run . runExc $- (return 1 `add` throwExc "bummer1") `alttry`+ run . runError $+ (return 1 `add` throwError "bummer1") `alttry` (return 10),- run . runExc $+ run . runError $ (return 10) `alttry`- (return 1 `add` throwExc "bummer2"),- run . runExc $+ (return 1 `add` throwError "bummer2"),+ run . runError $ (return 10) `alttry` return 20,- run . runExc $- (return 1 `add` throwExc "bummer1") `alttry`- (return 1 `add` throwExc "bummer2")+ run . runError $+ (return 1 `add` throwError "bummer1") `alttry`+ (return 1 `add` throwError "bummer2") ] case_Failure1_Effect :: Assertion
test/Control/Eff/Lift/Test.hs view
@@ -113,10 +113,10 @@ modify ("end":) return r - runErrorStr = asEStr . runExc+ runErrorStr = asEStr . runError asEStr :: m (Either String a) -> m (Either String a) asEStr = id- exfn True = throwExc $ ("thrown")+ exfn True = throwError $ ("thrown") exfn False = return True -- Now, the behavior of the dynamic Exception and Error effect is consistent.@@ -131,13 +131,13 @@ where test2 = do runLift (tf True) >>= print; runLift (tf False) >>= print tf x = runReader (runState (runErrorStr (testc m)) ([]::[String])) (x::Bool)- runErrorStr = asEStr . runExc+ runErrorStr = asEStr . runError asEStr :: m (Either String a) -> m (Either String a) asEStr = id m = do modify ("begin":) x <- ask- r <- exfn x `catchDynE` (\ (MyException s) -> throwExc s)+ r <- exfn x `catchDynE` (\ (MyException s) -> throwError s) modify ("end":) return r @@ -152,7 +152,7 @@ where test2' = do runLift (tf True) >>= print; runLift (tf False) >>= print tf x = runReader (runState (runErrorStr (testc m)) ([]::[String])) (x::Bool)- runErrorStr = asEStr . runExc+ runErrorStr = asEStr . runError asEStr :: m (Either String a) -> m (Either String a) asEStr = id m = do@@ -173,7 +173,7 @@ where test3 = do runLift (tf True) >>= print; runLift (tf False) >>= print tf x = runReader (runState (runErrorStr (testc m)) ([]::[String])) (x::Bool)- runErrorStr = asEStr . runExc+ runErrorStr = asEStr . runError asEStr :: m (Either String a) -> m (Either String a) asEStr = id m = do@@ -201,7 +201,7 @@ tf x = runReader (runState m1 ([]::[String])) (x::Bool) m1 = do modify ("init":)- testc (transactionState (ProxyState :: ProxyState [String]) m)+ testc (transactionState (TxState :: TxState [String]) m) m = do modify ("begin":) x <- ask
test/Control/Eff/State/LazyState/Test.hs view
@@ -60,8 +60,8 @@ case_LazierState_ex5 = let -- the annotations below are needed for assertEqual- ex5Run :: Either [Int] () = fst . run . runStateLazy (undefined::[Int]) . runExc $ lex5- ex51Run :: Either [Int] ((), [Int]) = run . runExc . runStateLazy (undefined::[Int]) $ lex5+ ex5Run :: Either [Int] () = fst . run . runStateLazy (undefined::[Int]) . runError $ lex5+ ex51Run :: Either [Int] ((), [Int]) = run . runError . runStateLazy (undefined::[Int]) $ lex5 in assertEqual "LazyState ex5" (Left ones) ex5Run >> assertEqual "LazyState ex51" (Left ones) ex51Run@@ -75,7 +75,7 @@ lex5 = do lex31 x <- lget- throwExc ((take 5 x)::[Int])+ throwError ((take 5 x)::[Int]) case_LazierState_st :: Assertion case_LazierState_st = let
test/Control/Eff/State/Strict/Test.hs view
@@ -77,25 +77,25 @@ , Member (Exc [Char]) r) => Eff r b tes1 = do incr- throwExc "exc"+ throwError "exc" where incr = get >>= put . (+ (1::Int)) case_Strict1_State_ter1 :: Assertion case_Strict1_State_ter1 = (Left "exc" :: Either String Int,2) @=?- (run $ runState (runExc tes1) (1::Int))+ (run $ runState (runError tes1) (1::Int)) case_Strict1_State_ter2 :: Assertion case_Strict1_State_ter2 = (Left "exc" :: Either String (Int,Int)) @=?- (run $ runExc (runState tes1 (1::Int)))+ (run $ runError (runState tes1 (1::Int))) teCatch :: Member (Exc String) r => Eff r a -> Eff r [Char]-teCatch m = catchExc (m >> return "done") (\e -> return (e::String))+teCatch m = catchError (m >> return "done") (\e -> return (e::String)) case_Strict1_State_ter3 :: Assertion case_Strict1_State_ter3 = (Right "exc" :: Either String String,2) @=?- (run $ runState (runExc (teCatch tes1)) (1::Int))+ (run $ runState (runError (teCatch tes1)) (1::Int)) case_Strict1_State_ter4 :: Assertion case_Strict1_State_ter4 = (Right ("exc",2) :: Either String (String,Int)) @=?- (run $ runExc (runState (teCatch tes1) (1::Int)))+ (run $ runError (runState (teCatch tes1) (1::Int)))