packages feed

polysemy-zoo 0.6.0.1 → 0.7.0.0

raw patch · 11 files changed

+338/−185 lines, 11 filesdep +compactdep +exceptionsdep +streamingdep −binarydep −bytestringdep −hedisdep ~polysemydep ~polysemy-pluginnew-uploaderPVP ok

version bump matches the API change (PVP)

Dependencies added: compact, exceptions, streaming, text

Dependencies removed: binary, bytestring, hedis

Dependency ranges changed: polysemy, polysemy-plugin

API changes (from Hackage documentation)

- Polysemy.Alias: type InterpreterOf e r = forall x. Sem (e : r) x -> Sem r x
- Polysemy.KVStore: runKVStoreInRedis :: (Member (Embed Redis) r, Member (Error Reply) r, Binary k, Binary v) => (k -> ByteString) -> Sem (KVStore k v : r) a -> Sem r a
- Polysemy.Redis.Utils: Path :: ByteString -> Path
- Polysemy.Redis.Utils: [getPath] :: Path -> ByteString
- Polysemy.Redis.Utils: getFromRedis :: Binary a => ByteString -> a
- Polysemy.Redis.Utils: instance Data.String.IsString Polysemy.Redis.Utils.Path
- Polysemy.Redis.Utils: instance GHC.Classes.Eq Polysemy.Redis.Utils.Path
- Polysemy.Redis.Utils: instance GHC.Classes.Ord Polysemy.Redis.Utils.Path
- Polysemy.Redis.Utils: instance GHC.Show.Show Polysemy.Redis.Utils.Path
- Polysemy.Redis.Utils: newtype Path
- Polysemy.Redis.Utils: putForRedis :: Binary a => a -> ByteString
- Polysemy.SetStore: runSetStoreInRedis :: (Member (Embed Redis) r, Member (Error Reply) r, Binary k, Binary v) => (k -> Path) -> InterpreterOf (SetStore k v) r
- Polysemy.Tagged: [Tagged] :: forall k e m a. e m a -> Tagged k e m a
- Polysemy.Tagged: newtype Tagged k e m a
- Polysemy.Tagged: retag :: forall k1 k2 e r a. Member (Tagged k2 e) r => Sem (Tagged k1 e : r) a -> Sem r a
- Polysemy.Tagged: tag :: forall k e r a. Member (Tagged k e) r => Sem (e : r) a -> Sem r a
- Polysemy.Tagged: untag :: forall k e r a. Sem (Tagged k e : r) a -> Sem (e : r) a
+ Polysemy.ConstraintAbsorber.MonadCatch: absorbMonadCatch :: Member (Error SomeException) r => (MonadCatch (Sem r) => Sem r a) -> Sem r a
+ Polysemy.ConstraintAbsorber.MonadCatch: absorbMonadThrow :: Member (Error SomeException) r => (MonadThrow (Sem r) => Sem r a) -> Sem r a
+ Polysemy.ConstraintAbsorber.MonadCatch: class (Typeable e, Show e) => Exception e
+ Polysemy.ConstraintAbsorber.MonadCatch: data SomeException
+ Polysemy.ConstraintAbsorber.MonadCatch: displayException :: Exception e => e -> String
+ Polysemy.ConstraintAbsorber.MonadCatch: fromException :: Exception e => SomeException -> Maybe e
+ Polysemy.ConstraintAbsorber.MonadCatch: instance forall (m :: * -> *) k (s' :: k). GHC.Base.Applicative m => GHC.Base.Applicative (Polysemy.ConstraintAbsorber.MonadCatch.Action m s')
+ Polysemy.ConstraintAbsorber.MonadCatch: instance forall (m :: * -> *) k (s' :: k). GHC.Base.Functor m => GHC.Base.Functor (Polysemy.ConstraintAbsorber.MonadCatch.Action m s')
+ Polysemy.ConstraintAbsorber.MonadCatch: instance forall (m :: * -> *) k (s' :: k). GHC.Base.Monad m => GHC.Base.Monad (Polysemy.ConstraintAbsorber.MonadCatch.Action m s')
+ Polysemy.ConstraintAbsorber.MonadCatch: instance forall k (m :: * -> *) (s' :: k). (GHC.Base.Monad m, Data.Reflection.Reifies s' (Polysemy.ConstraintAbsorber.MonadCatch.CatchDict m)) => Control.Monad.Catch.MonadCatch (Polysemy.ConstraintAbsorber.MonadCatch.Action m s')
+ Polysemy.ConstraintAbsorber.MonadCatch: instance forall k (m :: * -> *) (s' :: k). (GHC.Base.Monad m, Data.Reflection.Reifies s' (Polysemy.ConstraintAbsorber.MonadCatch.CatchDict m)) => Control.Monad.Catch.MonadThrow (Polysemy.ConstraintAbsorber.MonadCatch.Action m s')
+ Polysemy.ConstraintAbsorber.MonadCatch: runMonadCatch :: Exception e => (Maybe e -> e') -> Sem (Error SomeException : (Error e' : r)) a -> Sem r (Either e' a)
+ Polysemy.ConstraintAbsorber.MonadCatch: runMonadCatchAsText :: Sem (Error SomeException : (Error Text : r)) a -> Sem r (Either Text a)
+ Polysemy.ConstraintAbsorber.MonadCatch: toException :: Exception e => e -> SomeException
+ Polysemy.Input.Streaming: exhaust :: Member (Input i) r => Stream (Of i) (Sem r) a
+ Polysemy.Input.Streaming: runInputViaInfiniteStream :: forall i r. Stream (Of i) (Sem r) Void -> InterpreterFor (Input i) r
+ Polysemy.Input.Streaming: runInputViaStream :: Stream (Of i) (Sem r) () -> InterpreterFor (Input (Maybe i)) r
+ Polysemy.Input.Streaming: yieldInput :: Member (Input i) r => Stream (Of i) (Sem r) ()
+ Polysemy.Input.Streaming: yieldRace :: Members '[Final IO, Input i1, Input i2] r => Stream (Of (Either i1 i2)) (Sem r) ()
+ Polysemy.Reader.Compact: runReaderWithCompacted :: forall r i a. Member (Embed IO) r => i -> Sem (Reader i : r) a -> Sem r a
+ Polysemy.Reader.Compact: runReaderWithExistingCompacted :: forall r i a. Member (Embed IO) r => Compact i -> Sem (Reader i : r) a -> Sem r a
- Polysemy.EndState: getEndState :: forall s_aBgI r_aBhB. MemberWithError (EndState s_aBgI) r_aBhB => Sem r_aBhB s_aBgI
+ Polysemy.EndState: getEndState :: forall s_aA6w r_aA7p. MemberWithError (EndState s_aA6w) r_aA7p => Sem r_aA7p s_aA6w
- Polysemy.Floodgate: hold :: forall r_apIf. MemberWithError Floodgate r_apIf => Sem r_apIf () -> Sem r_apIf ()
+ Polysemy.Floodgate: hold :: forall r_aoMw. MemberWithError Floodgate r_aoMw => Sem r_aoMw () -> Sem r_aoMw ()
- Polysemy.Floodgate: release :: forall r_apIh. MemberWithError Floodgate r_apIh => Sem r_apIh ()
+ Polysemy.Floodgate: release :: forall r_aoMy. MemberWithError Floodgate r_aoMy => Sem r_aoMy ()
- Polysemy.Fresh: fresh :: forall uniq_av8A r_av9t. MemberWithError (Fresh uniq_av8A) r_av9t => Sem r_av9t uniq_av8A
+ Polysemy.Fresh: fresh :: forall uniq_augT r_auhM. MemberWithError (Fresh uniq_augT) r_auhM => Sem r_auhM uniq_augT
- Polysemy.KVStore: lookupKV :: forall k_aGzJ v_aGzK r_aGBD. MemberWithError (KVStore k_aGzJ v_aGzK) r_aGBD => k_aGzJ -> Sem r_aGBD (Maybe v_aGzK)
+ Polysemy.KVStore: lookupKV :: forall k_ayqZ v_ayr0 r_aysT. MemberWithError (KVStore k_ayqZ v_ayr0) r_aysT => k_ayqZ -> Sem r_aysT (Maybe v_ayr0)
- Polysemy.KVStore: updateKV :: forall k_aGzM v_aGzN r_aGBF. MemberWithError (KVStore k_aGzM v_aGzN) r_aGBF => k_aGzM -> Maybe v_aGzN -> Sem r_aGBF ()
+ Polysemy.KVStore: updateKV :: forall k_ayr2 v_ayr3 r_aysV. MemberWithError (KVStore k_ayr2 v_ayr3) r_aysV => k_ayr2 -> Maybe v_ayr3 -> Sem r_aysV ()
- Polysemy.Random: random :: forall r_aAsA x_aAqQ. (MemberWithError Random r_aAsA, Random x_aAqQ) => Sem r_aAsA x_aAqQ
+ Polysemy.Random: random :: forall r_azvr x_aztH. (MemberWithError Random r_azvr, Random x_aztH) => Sem r_azvr x_aztH
- Polysemy.Random: randomR :: forall r_aAsB x_aAqS. (MemberWithError Random r_aAsB, Random x_aAqS) => (x_aAqS, x_aAqS) -> Sem r_aAsB x_aAqS
+ Polysemy.Random: randomR :: forall r_azvs x_aztJ. (MemberWithError Random r_azvs, Random x_aztJ) => (x_aztJ, x_aztJ) -> Sem r_azvs x_aztJ
- Polysemy.SetStore: addS :: forall k_aJU6 v_aJU7 r_aJX2. MemberWithError (SetStore k_aJU6 v_aJU7) r_aJX2 => k_aJU6 -> v_aJU7 -> Sem r_aJX2 ()
+ Polysemy.SetStore: addS :: forall k_aByo v_aByp r_aBBk. MemberWithError (SetStore k_aByo v_aByp) r_aBBk => k_aByo -> v_aByp -> Sem r_aBBk ()
- Polysemy.SetStore: delS :: forall k_aJU9 v_aJUa r_aJX5. MemberWithError (SetStore k_aJU9 v_aJUa) r_aJX5 => k_aJU9 -> v_aJUa -> Sem r_aJX5 ()
+ Polysemy.SetStore: delS :: forall k_aByr v_aBys r_aBBn. MemberWithError (SetStore k_aByr v_aBys) r_aBBn => k_aByr -> v_aBys -> Sem r_aBBn ()
- Polysemy.SetStore: memberS :: forall k_aJUc v_aJUd r_aJX8. MemberWithError (SetStore k_aJUc v_aJUd) r_aJX8 => k_aJUc -> v_aJUd -> Sem r_aJX8 Bool
+ Polysemy.SetStore: memberS :: forall k_aByu v_aByv r_aBBq. MemberWithError (SetStore k_aByu v_aByv) r_aBBq => k_aByu -> v_aByv -> Sem r_aBBq Bool
- Polysemy.SetStore: runSetStoreAsKVStore :: (Member (KVStore k (Set v)) r, Ord v) => InterpreterOf (SetStore k v) r
+ Polysemy.SetStore: runSetStoreAsKVStore :: (Member (KVStore k (Set v)) r, Ord v) => Sem (SetStore k v : r) x -> Sem r x

Files

ChangeLog.md view
@@ -1,5 +1,23 @@ # Changelog for polysemy-zoo +## 0.7.0.0 (2020-02-14)+### Breaking Changes+- `Tagged` has been migrated to `polysemy` proper.+- `Polysemy.Alias` and `InterpreterOf` has been removed in favor of+    `InterpreterFor`, which is now part of `polysemy` proper+    (thanks to @bolt12).+- Removed `runKVStoreInRedis`, `runSetStoreInRedis`, and `Polysemy.Redis.Utils`+    due to lack of use.++### Other Changes+- Added `MonadThrow` and `MonadCatch` constraint absorbers which operate+    via `Error SomeException` (thanks to @adamConnerSax).+- Added `Polysemy.Input.Streaming`, which offers+    [streaming](https://hackage.haskell.org/package/streaming) interoperability.+- Added `Polysemy.Reader.Compact`, which is useful for `Reader` effects+    which provide a large structure (thanks to @spacekitteh).++ ## 0.6.0.1 (2019-09-12)  - Fixed the implementation of `atomicPut`
polysemy-zoo.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: 508b2d70f45ca899d68cc756e99c4a93128f7748848feefea756030db96c9c94+-- hash: 3ca3f0fd7140b4210529e77e057687ebd67bb4477155611458e964afa5cdc192  name:           polysemy-zoo-version:        0.6.0.1+version:        0.7.0.0 synopsis:       Experimental, user-contributed effects and interpreters for polysemy description:    Please see the README on GitHub at <https://github.com/isovector/polysemy-zoo#readme> category:       Polysemy@@ -29,9 +29,9 @@  library   exposed-modules:-      Polysemy.Alias       Polysemy.Capture       Polysemy.ConstraintAbsorber+      Polysemy.ConstraintAbsorber.MonadCatch       Polysemy.ConstraintAbsorber.MonadCont       Polysemy.ConstraintAbsorber.MonadError       Polysemy.ConstraintAbsorber.MonadReader@@ -48,17 +48,17 @@       Polysemy.Floodgate       Polysemy.Fresh       Polysemy.IdempotentLowering+      Polysemy.Input.Streaming       Polysemy.KVStore       Polysemy.Operators       Polysemy.Random+      Polysemy.Reader.Compact       Polysemy.Reader.More-      Polysemy.Redis.Utils       Polysemy.RevState       Polysemy.SetStore       Polysemy.Several       Polysemy.Shift       Polysemy.Shift.Internal-      Polysemy.Tagged   other-modules:       Paths_polysemy_zoo   hs-source-dirs:@@ -68,18 +68,19 @@   build-depends:       async >=2.2 && <3     , base >=4.9 && <5-    , binary >=0.8.5.1 && <0.9-    , bytestring >=0.10.8.2 && <0.11+    , compact >=0.1.0.1     , constraints >=0.10.1 && <0.12     , containers >=0.5 && <0.7     , contravariant <2+    , exceptions >=0.10.0 && <0.11     , ghc-prim >=0.5.2 && <0.6-    , hedis >=0.10 && <0.13     , mtl >=2.0.1.0 && <3.0.0.0-    , polysemy >=1.2.0.0+    , polysemy >=1.2.1.0     , polysemy-plugin >=0.2     , random >=1.1 && <1.2     , reflection >=2.1.4 && <3.0.0+    , streaming+    , text >=1.1.0 && <1.3     , transformers >=0.5.2.0 && <0.6   default-language: Haskell2010 @@ -107,13 +108,12 @@   build-depends:       async >=2.2 && <3     , base >=4.9 && <5-    , binary >=0.8.5.1 && <0.9-    , bytestring >=0.10.8.2 && <0.11+    , compact >=0.1.0.1     , constraints >=0.10.1 && <0.12     , containers >=0.5 && <0.7     , contravariant <2+    , exceptions >=0.10.0 && <0.11     , ghc-prim >=0.5.2 && <0.6-    , hedis >=0.10 && <0.13     , hspec >=2.6.0 && <3     , mtl >=2.0.1.0 && <3.0.0.0     , polysemy >=1.2.0.0@@ -121,5 +121,7 @@     , polysemy-zoo     , random >=1.1 && <1.2     , reflection >=2.1.4 && <3.0.0+    , streaming+    , text >=1.1.0 && <1.3     , transformers >=0.5.2.0 && <0.6   default-language: Haskell2010
− src/Polysemy/Alias.hs
@@ -1,6 +0,0 @@-module Polysemy.Alias where--import Polysemy--type InterpreterOf e r = forall x.  Sem (e ': r) x -> Sem r x-
+ src/Polysemy/ConstraintAbsorber/MonadCatch.hs view
@@ -0,0 +1,125 @@+{-# LANGUAGE AllowAmbiguousTypes         #-}+{-# LANGUAGE FlexibleContexts            #-}+{-# LANGUAGE GADTs                       #-}+{-# LANGUAGE GeneralizedNewtypeDeriving  #-}+{-# LANGUAGE RankNTypes                  #-}+{-# LANGUAGE ScopedTypeVariables         #-}+{-# LANGUAGE TypeApplications            #-}+{-# LANGUAGE UndecidableInstances        #-}++module Polysemy.ConstraintAbsorber.MonadCatch+  (+    -- * Constraint Absorbers+    absorbMonadThrow+  , absorbMonadCatch+  -- * run helper+  , runMonadCatch+  , runMonadCatchAsText+    -- * Re-exports+  , Exception(..)+  , SomeException+  )+where++import qualified Control.Monad.Catch           as C+import           Control.Monad.Catch            ( Exception(..)+                                                , SomeException+                                                , toException+                                                )++import qualified Data.Text                     as T+import           Polysemy+import           Polysemy.ConstraintAbsorber+import qualified Polysemy.Error                as E+++------------------------------------------------------------------------------+-- | Like 'E.runError' but applies a given function from 'SomeException'+-- to some other type, typically something less opaque.+-- e.g.:+--  @runErrorForMonadCatch C.displayException@+-- +-- @since 0.7.0.0+runMonadCatch+  :: Exception e+  => (Maybe e -> e')+  -> Sem (E.Error C.SomeException : E.Error e' : r) a+  -> Sem r (Either e' a)+runMonadCatch f = E.runError . E.mapError (f . C.fromException)++runMonadCatchAsText+  :: Sem (E.Error C.SomeException : E.Error T.Text : r) a+  -> Sem r (Either T.Text a)+runMonadCatchAsText = E.runError . E.mapError (T.pack . C.displayException)++++-- | Introduce a local 'S.MonadCatch' constraint on 'Sem' --- allowing it to+-- interop nicely with exceptions+--+-- @since 0.7.0.0+absorbMonadCatch+  :: Member (E.Error C.SomeException) r+  => (C.MonadCatch (Sem r) => Sem r a)+       -- ^ A computation that requires an instance of 'C.MonadCatch'+       -- or 'C.MonadThrow' for+       -- 'Sem'. This might be something with type @'C.MonadCatch' e m => m a@.+  -> Sem r a+absorbMonadCatch =+  absorbWithSem @C.MonadCatch @Action (CatchDict E.throw E.catch) (Sub Dict)+{-# INLINABLE absorbMonadCatch #-}++-- | Introduce a local 'S.MonadThrow' constraint on 'Sem' --- allowing it to+-- interop nicely with exceptions+--+-- @since 0.7.0.0+absorbMonadThrow+  :: Member (E.Error C.SomeException) r+  => (C.MonadThrow (Sem r) => Sem r a)+       -- ^ A computation that requires an instance of 'C.MonadCatch'+       -- or 'C.MonadThrow' for+       -- 'Sem'. This might be something with type @'C.MonadCatch' e m => m a@.+  -> Sem r a+absorbMonadThrow = absorbMonadCatch+{-# INLINABLE absorbMonadThrow #-}++------------------------------------------------------------------------------+-- | A dictionary of the functions we need to supply+-- to make an instance of Error+data CatchDict m = CatchDict+  { throwM_ :: forall a. C.SomeException -> m a+  , catch_ :: forall a. m a -> (C.SomeException -> m a) -> m a+  }+++------------------------------------------------------------------------------+-- | Wrapper for a monadic action with phantom+-- type parameter for reflection.+-- Locally defined so that the instance we are going+-- to build with reflection must be coherent, that is+-- there cannot be orphans.+newtype Action m s' a = Action { action :: m a }+  deriving (Functor, Applicative, Monad)+++------------------------------------------------------------------------------+-- | Given a reifiable mtl Error dictionary,+-- we can make an instance of @MonadError@ for the action+-- wrapped in @Action@.+instance ( Monad m+         , Reifies s' (CatchDict m)+         ) => C.MonadThrow (Action m s') where+  throwM e = Action $ throwM_ (reflect $ Proxy @s') (C.toException e)+  {-# INLINEABLE throwM #-}++instance ( Monad m+         , Reifies s' (CatchDict m)+         )  => C.MonadCatch (Action m s') where+  catch x f =+    let catchF = catch_ (reflect $ Proxy @s')+    in Action $ (action x) `catchF` \e -> case C.fromException e of+      Just e' -> action $ f e'+      _ -> throwM_ (reflect $ Proxy @s') (C.toException e)+  {-# INLINEABLE catch #-}++
+ src/Polysemy/Input/Streaming.hs view
@@ -0,0 +1,86 @@+module Polysemy.Input.Streaming+  ( -- * Underlying Effect+    module Polysemy.Input++    -- * Actions+  , yieldInput+  , yieldRace+  , exhaust++    -- * Intepretations+  , runInputViaStream+  , runInputViaInfiniteStream+  ) where++import qualified Control.Concurrent.Async as A+import           Data.Functor.Of+import           Data.Void+import           Polysemy+import           Polysemy.Final+import           Polysemy.Input+import           Polysemy.State+import qualified Streaming as S+import qualified Streaming.Prelude as S++++runInputViaStream+    :: S.Stream (Of i) (Sem r) ()+    -> InterpreterFor (Input (Maybe i)) r+runInputViaStream stream+  = evalState (Just stream)+  . reinterpret ( \Input ->+      get >>= \case+        Nothing -> pure Nothing+        Just s ->+          raise (S.inspect s) >>= \case+            Left () -> pure Nothing+            Right (i :> s') -> do+              put $ Just s'+              pure $ Just i+  )+++runInputViaInfiniteStream+    :: forall i r+     . S.Stream (Of i) (Sem r) Void+    -> InterpreterFor (Input i) r+runInputViaInfiniteStream stream+  = evalState stream+  . reinterpret ( \Input -> do+      s <- get+      raise (S.inspect s) >>= \case+        Left g -> absurd g+        Right (i :> s') -> do+          put s'+          pure i+  )+++yieldRace+    :: Members+        '[ Final IO+         , Input i1+         , Input i2+         ] r+    => S.Stream (S.Of (Either i1 i2)) (Sem r) ()+yieldRace = do+  z <- S.lift $ withStrategicToFinal $ do+         input1 <- runS input+         input2 <- runS input+         pure $ fmap sequenceEither $ A.race input1 input2+  S.yield z+++sequenceEither :: Functor f => Either (f a) (f b) -> f (Either a b)+sequenceEither (Left fa) = Left <$> fa+sequenceEither (Right fb) = Right <$> fb+++yieldInput :: Member (Input i) r => S.Stream (Of i) (Sem r) ()+yieldInput = S.lift input >>= S.yield+++exhaust :: Member (Input i) r => S.Stream (Of i) (Sem r) a+exhaust = S.repeatM input+
src/Polysemy/KVStore.hs view
@@ -16,18 +16,12 @@     -- * Interpretations   , runKVStoreAsState   , runKVStorePurely-  , runKVStoreInRedis   ) where -import           Control.Monad-import           Data.Binary (Binary)-import           Data.ByteString (ByteString) import qualified Data.Map as M import           Data.Maybe (isJust)-import qualified Database.Redis as R import           Polysemy import           Polysemy.Error-import           Polysemy.Redis.Utils import           Polysemy.State  @@ -104,31 +98,4 @@     -> Sem r (M.Map k v, a) runKVStorePurely m = runState m . runKVStoreAsState {-# INLINE runKVStorePurely #-}---runKVStoreInRedis-    :: ( Member (Embed R.Redis) r-       , Member (Error R.Reply) r-       , Binary k-       , Binary v-       )-    => (k -> ByteString)-    -> Sem (KVStore k v ': r) a-    -> Sem r a-runKVStoreInRedis pf = interpret $ \case-  LookupKV k -> do-    res <- fromEitherM $ R.hget (pf k) $ putForRedis k-    pure $ fmap getFromRedis res--  UpdateKV k Nothing ->-    void . fromEitherM-         . R.hdel (pf k)-         . pure-         $ putForRedis k--  UpdateKV k (Just v) ->-    void . fromEitherM-         . R.hset (pf k) (putForRedis k)-         $ putForRedis v-{-# INLINE runKVStoreInRedis #-} 
+ src/Polysemy/Reader/Compact.hs view
@@ -0,0 +1,37 @@+module Polysemy.Reader.Compact where++import           Polysemy+import           Polysemy.Reader++import           Data.Compact++-----------------------------------------------------------------------------+-- | Run a 'Reader' effect by compacting a value; otherwise behaves as normal.+-- Useful for 'Reader' effects which provide a large structure.+runReaderWithCompacted+    :: forall r i a+     . Member (Embed IO) r+    => i+    -> Sem (Reader i ': r) a+    -> Sem r a+runReaderWithCompacted i sem = do+    compacted <- embed (compactWithSharing i)+    runReaderWithExistingCompacted compacted sem+{-# INLINE runReaderWithCompacted #-}++-----------------------------------------------------------------------------+-- | Run a 'Reader' effect with a value in a compact region. Will not add +-- 'local' values to the existing region, but will create a new region for it.+runReaderWithExistingCompacted+    :: forall r i a+     . Member (Embed IO) r+    => Compact i+    -> Sem (Reader i ': r) a+    -> Sem r a+runReaderWithExistingCompacted i = interpretH $ \case+    Ask       -> pureT (getCompact i)+    Local f m -> do+        mm <- runT m+        let transformed = f (getCompact i)+        raise $ runReaderWithCompacted transformed mm+{-# INLINE runReaderWithExistingCompacted #-}
− src/Polysemy/Redis/Utils.hs
@@ -1,24 +0,0 @@-{-# LANGUAGE GeneralizedNewtypeDeriving #-}--module Polysemy.Redis.Utils where--import           Data.Binary (Binary)-import qualified Data.Binary as B-import           Data.Binary.Get (runGet)-import           Data.Binary.Put (runPut)-import           Data.ByteString (ByteString)-import qualified Data.ByteString.Lazy.Char8 as L-import           GHC.Exts---newtype Path = Path { getPath :: ByteString }-  deriving (Eq, Ord, Show, IsString)---putForRedis :: Binary a => a -> ByteString-putForRedis = L.toStrict . runPut . B.put---getFromRedis :: Binary a => ByteString -> a-getFromRedis = runGet B.get . L.fromStrict-
src/Polysemy/SetStore.hs view
@@ -2,16 +2,10 @@  module Polysemy.SetStore where -import           Control.Monad-import           Data.Binary (Binary) import           Data.Foldable import qualified Data.Set as S-import qualified Database.Redis as R import           Polysemy-import           Polysemy.Alias-import           Polysemy.Error import           Polysemy.KVStore-import           Polysemy.Redis.Utils   @@ -27,7 +21,7 @@     :: ( Member (KVStore k (S.Set v)) r        , Ord v        )-    => InterpreterOf (SetStore k v) r+    => Sem (SetStore k v ': r) x -> Sem r x runSetStoreAsKVStore = interpret $ \case   AddS k v ->     lookupKV k >>= \case@@ -39,29 +33,4 @@   MemberS k v ->     pure . maybe False (S.member v) =<< lookupKV k {-# INLINE runSetStoreAsKVStore #-}---runSetStoreInRedis-    :: ( Member (Embed R.Redis) r-       , Member (Error R.Reply) r-       , Binary k-       , Binary v-       )-    => (k -> Path)-    -> InterpreterOf (SetStore k v) r-runSetStoreInRedis pf = interpret $ \case-  AddS k v -> void-            . fromEitherM-            . R.sadd (getPath $ pf k)-            . pure-            $ putForRedis v-  DelS k v -> void-            . fromEitherM-            . R.srem (getPath $ pf k)-            . pure-            $ putForRedis v-  MemberS k v -> fromEitherM-               . R.sismember (getPath $ pf k)-               $ putForRedis v-{-# INLINE runSetStoreInRedis #-} 
− src/Polysemy/Tagged.hs
@@ -1,77 +0,0 @@-module Polysemy.Tagged-  (-    -- * Effect-    Tagged (..)--    -- * Actions-  , tag--    -- * Interpretations-  , untag-  , retag-  ) where--import Polysemy-import Polysemy.Internal-import Polysemy.Internal.Union------------------------------------------------------------------------------------ | An effect for annotating effects and disambiguating identical effects.-newtype Tagged k e m a where-  Tagged :: forall k e m a. e m a -> Tagged k e m a----------------------------------------------------------------------------------- | Tag uses of an effect, effectively gaining access to the--- tagged effect locally.------ This may be used to create @tagged-@ variants of regular actions.------ For example (the type applications aren't needed when using @polysemy-plugin@):------ @--- taggedLocal :: forall k i r a---              . 'Member' ('Tagged' k ('Polysemy.Reader.Reader' i)) r---             => (i -> i)---             -> 'Sem' r a---             -> 'Sem' r a--- taggedLocal f m =---   'tag' \@k \@('Polysemy.Reader.Reader' i) $ 'Polysemy.Reader.local' \@i f ('raise' m)--- @----tag :: forall k e r a-     . Member (Tagged k e) r-    => Sem (e ': r) a-    -> Sem r a-tag = hoistSem $ \u -> case decomp u of-  Right (Weaving e s wv ex ins) ->-    injWeaving $ Weaving (Tagged e) s (tag . wv) ex ins-  Left g -> hoist tag g-{-# INLINE tag #-}----------------------------------------------------------------------------------- | Run a @'Tagged' k e@ effect through reinterpreting it to @e@-untag :: forall k e r a-       . Sem (Tagged k e ': r) a-      -> Sem (e ': r) a--- TODO(KingoftheHomeless): I think this is safe to replace with 'unsafeCoerce',--- but doing so probably worsens performance, as it hampers optimizations.--- Once GHC 8.10 rolls out, I will benchmark and compare.-untag = hoistSem $ \u -> case decompCoerce u of-  Right (Weaving (Tagged e) s wv ex ins) ->-    Union SZ (Weaving e s (untag . wv) ex ins)-  Left g -> hoist untag g-{-# INLINE untag #-}----------------------------------------------------------------------------------- | Transform a @'Tagged' k1 e@ effect into a @'Tagged' k2 e@ effect-retag :: forall k1 k2 e r a-       . Member (Tagged k2 e) r-      => Sem (Tagged k1 e ': r) a-      -> Sem r a-retag = hoistSem $ \u -> case decomp u of-  Right (Weaving (Tagged e) s wv ex ins) ->-    injWeaving $ Weaving (Tagged e) s (retag . wv) ex ins-  Left g -> hoist retag g-{-# INLINE retag #-}-
test/ConstraintAbsorberSpec.hs view
@@ -1,6 +1,8 @@+{-# LANGUAGE OverloadedStrings   #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications    #-} + module ConstraintAbsorberSpec where  import           Polysemy@@ -13,14 +15,17 @@ import           Polysemy.ConstraintAbsorber.MonadState import           Polysemy.ConstraintAbsorber.MonadWriter import           Polysemy.ConstraintAbsorber.MonadError+import           Polysemy.ConstraintAbsorber.MonadCatch  import           Test.Hspec-import           Control.Monad                 as M+import qualified Control.Monad                 as M+import           Data.Maybe                     ( fromMaybe )  import qualified Control.Monad.Reader.Class    as S import qualified Control.Monad.Writer.Class    as S import qualified Control.Monad.State.Class     as S import qualified Control.Monad.Error.Class     as S+import qualified Control.Monad.Catch           as S   {-@@ -46,6 +51,23 @@   M.when (n == 0) $ S.throwError "Zero!"   return n +data MyException = ZeroException | NegativeException | UnknownException deriving (Show, Eq)++instance S.Exception MyException++-- a different error handling option+throwOnZeroAndNegative :: S.MonadThrow m => Int -> m Int+throwOnZeroAndNegative n = do+  M.when (n == 0) $ S.throwM ZeroException+  M.when (n < 0) $ S.throwM NegativeException+  return n++-- this is dumb but it makes the point. +handleZero :: S.MonadThrow m => MyException -> m Int+handleZero ZeroException = return 0+handleZero e             = S.throwM e++ someOfAll   :: (S.MonadReader String m, S.MonadWriter [Int] m, S.MonadState Int m)   => m String@@ -93,8 +115,42 @@       modify (\m -> m - (n `div` 2))       return () +  it "should return (Right 1)." $ do+    flip shouldBe (Right 1) . run . runError $ absorbError $ throwOnZero 1   it "should return (Left \"Zero!\")." $ do     flip shouldBe (Left "Zero!") . run . runError $ absorbError $ throwOnZero 0++  let toMyException = fromMaybe UnknownException+  it "should return (Right 1)." $ do+    flip shouldBe (Right 1)+      . run+      . runMonadCatch toMyException+      $ absorbMonadThrow+      $ throwOnZeroAndNegative 1+  it "should return (Left ZeroException)." $ do+    flip shouldBe (Left ZeroException)+      . run+      . runMonadCatch toMyException+      $ absorbMonadThrow+      $ throwOnZeroAndNegative 0+  it "should return (Left \"ZeroException\")." $ do+    flip shouldBe (Left "ZeroException")+      . run+      . runMonadCatchAsText+      $ absorbMonadThrow+      $ throwOnZeroAndNegative 0+  it "should return (Right 0)." $ do+    flip shouldBe (Right 0)+      . run+      . runMonadCatch toMyException+      $ absorbMonadCatch+      $ S.catch (throwOnZeroAndNegative 0) handleZero+  it "should return (Left NegativeException)." $ do+    flip shouldBe (Left NegativeException)+      . run+      . runMonadCatch toMyException+      $ absorbMonadCatch+      $ S.catch (throwOnZeroAndNegative (-1)) handleZero    let runRWS         :: String