packages feed

polysemy 0.7.0.0 → 1.0.0.0

raw patch · 35 files changed

+780/−517 lines, 35 filesdep +type-errors-prettyPVP ok

version bump matches the API change (PVP)

Dependencies added: type-errors-pretty

API changes (from Hackage documentation)

- Polysemy: [Lift] :: {unLift :: m a} -> Lift m z a
- Polysemy: newtype Lift m (z :: Type -> Type) a
- Polysemy: sendM :: Member (Lift m) r => m a -> Sem r a
- Polysemy.Async: runAsync :: LastMember (Lift IO) r => Sem (Async : r) a -> Sem r a
- Polysemy.Async: runAsyncInIO :: Member (Lift IO) r => (forall x. Sem r x -> IO x) -> Sem (Async : r) a -> Sem r a
- Polysemy.Error: runErrorAsAnother :: forall e1 e2 r a. Member (Error e2) r => (e1 -> e2) -> Sem (Error e1 : r) a -> Sem r a
- Polysemy.Error: runErrorInIO :: (Typeable e, Member (Lift IO) r) => (forall x. Sem r x -> IO x) -> Sem (Error e : r) a -> Sem r (Either e a)
- Polysemy.IO: runEmbedded :: (MonadIO m, LastMember (Lift IO) r) => (forall x. m x -> IO x) -> Sem (Lift m : r) a -> Sem r a
- Polysemy.IO: runIO :: forall m r a. (MonadIO m, Member (Lift m) r) => Sem (Lift IO : r) a -> Sem r a
- Polysemy.Input: runConstInput :: i -> Sem (Input i : r) a -> Sem r a
- Polysemy.Input: runListInput :: [i] -> Sem (Input (Maybe i) : r) a -> Sem r a
- Polysemy.Input: runMonadicInput :: forall i r a. Sem r i -> Sem (Input i : r) a -> Sem r a
- Polysemy.Internal: [Lift] :: {unLift :: m a} -> Lift m z a
- Polysemy.Internal: instance Polysemy.Internal.Union.Member (Polysemy.Internal.Lift.Lift GHC.Types.IO) r => Control.Monad.IO.Class.MonadIO (Polysemy.Internal.Sem r)
- Polysemy.Internal: newtype Lift m (z :: Type -> Type) a
- Polysemy.Internal: sendM :: Member (Lift m) r => m a -> Sem r a
- Polysemy.Internal.Lift: [Lift] :: {unLift :: m a} -> Lift m z a
- Polysemy.Internal.Lift: newtype Lift m (z :: Type -> Type) a
- Polysemy.Internal.TH.Common: [cliArgs] :: ConLiftInfo -> [(Name, Type)]
- Polysemy.Internal.TH.Common: [cliResType] :: ConLiftInfo -> Type
- Polysemy.Internal.TH.Common: foldArrows :: Type -> [Type] -> Type
- Polysemy.Output: runBatchOutput :: forall o r a. Int -> Sem (Output o : r) a -> Sem (Output [o] : r) a
- Polysemy.Output: runFoldMapOutput :: forall o m r a. Monoid m => (o -> m) -> Sem (Output o : r) a -> Sem r (m, a)
- Polysemy.Output: runIgnoringOutput :: Sem (Output o : r) a -> Sem r a
- Polysemy.Output: runOutputAsList :: forall o r a. Sem (Output o : r) a -> Sem r ([o], a)
- Polysemy.Reader: runInputAsReader :: Member (Reader i) r => Sem (Input i : r) a -> Sem r a
- Polysemy.Resource: runResourceBase :: forall r a. LastMember (Lift IO) r => Sem (Resource : r) a -> Sem r a
- Polysemy.Resource: runResourceInIO :: forall r a. Member (Lift IO) r => (forall x. Sem r x -> IO x) -> Sem (Resource : r) a -> Sem r a
- Polysemy.State: runStateInIORef :: forall s r a. Member (Lift IO) r => IORef s -> Sem (State s : r) a -> Sem r a
- Polysemy.Trace: runIgnoringTrace :: Member (Lift IO) r => Sem (Trace : r) a -> Sem r a
- Polysemy.Trace: runOutputAsTrace :: (Show w, Member Trace r) => Sem (Output w : r) a -> Sem r a
- Polysemy.Trace: runTraceAsList :: Sem (Trace : r) a -> Sem r ([String], a)
- Polysemy.Trace: runTraceAsOutput :: Member (Output String) r => Sem (Trace : r) a -> Sem r a
- Polysemy.Trace: runTraceIO :: Member (Lift IO) r => Sem (Trace : r) a -> Sem r a
- Polysemy.Writer: runOutputAsWriter :: Member (Writer o) r => Sem (Output o : r) a -> Sem r a
+ Polysemy: [Embed] :: {unEmbed :: m a} -> Embed m z a
+ Polysemy: embed :: Member (Embed m) r => m a -> Sem r a
+ Polysemy: newtype Embed m (z :: Type -> Type) a
+ Polysemy.Async: asyncToIO :: LastMember (Embed IO) r => Sem (Async : r) a -> Sem r a
+ Polysemy.Async: lowerAsync :: Member (Embed IO) r => (forall x. Sem r x -> IO x) -> Sem (Async : r) a -> Sem r a
+ Polysemy.Embed: [Embed] :: {unEmbed :: m a} -> Embed m z a
+ Polysemy.Embed: embed :: Member (Embed m) r => m a -> Sem r a
+ Polysemy.Embed: newtype Embed m (z :: Type -> Type) a
+ Polysemy.Embed: runEmbedded :: forall m1 m2 r a. Member (Embed m2) r => (forall x. m1 x -> m2 x) -> Sem (Embed m1 : r) a -> Sem r a
+ Polysemy.Embed.Type: [Embed] :: {unEmbed :: m a} -> Embed m z a
+ Polysemy.Embed.Type: newtype Embed m (z :: Type -> Type) a
+ Polysemy.Error: lowerError :: (Typeable e, Member (Embed IO) r) => (forall x. Sem r x -> IO x) -> Sem (Error e : r) a -> Sem r (Either e a)
+ Polysemy.Error: mapError :: forall e1 e2 r a. Member (Error e2) r => (e1 -> e2) -> Sem (Error e1 : r) a -> Sem r a
+ Polysemy.IO: embedToMonadIO :: forall m r a. (MonadIO m, Member (Embed m) r) => Sem (Embed IO : r) a -> Sem r a
+ Polysemy.IO: lowerEmbedded :: (MonadIO m, LastMember (Embed IO) r) => (forall x. m x -> IO x) -> Sem (Embed m : r) a -> Sem r a
+ Polysemy.Input: runInputConst :: i -> Sem (Input i : r) a -> Sem r a
+ Polysemy.Input: runInputList :: [i] -> Sem (Input (Maybe i) : r) a -> Sem r a
+ Polysemy.Input: runInputSem :: forall i r a. Sem r i -> Sem (Input i : r) a -> Sem r a
+ Polysemy.Internal: [Embed] :: {unEmbed :: m a} -> Embed m z a
+ Polysemy.Internal: embed :: Member (Embed m) r => m a -> Sem r a
+ Polysemy.Internal: instance Polysemy.Internal.Union.Member (Polysemy.Embed.Type.Embed GHC.Types.IO) r => Control.Monad.IO.Class.MonadIO (Polysemy.Internal.Sem r)
+ Polysemy.Internal: newtype Embed m (z :: Type -> Type) a
+ Polysemy.Internal.TH.Common: [cliEffRes] :: ConLiftInfo -> Type
+ Polysemy.Internal.TH.Common: [cliFunArgs] :: ConLiftInfo -> [(Name, Type)]
+ Polysemy.Internal.TH.Common: foldArrowTs :: Type -> [Type] -> Type
+ Polysemy.Internal.TH.Common: infixr 1 :->
+ Polysemy.Internal.TH.Common: pattern (:->) :: Type -> Type -> Type
+ Polysemy.Internal.TH.Common: splitArrowTs :: Type -> [Type]
+ Polysemy.NonDet: nonDetToError :: Member (Error e) r => e -> Sem (NonDet : r) a -> Sem r a
+ Polysemy.NonDet: runNonDetMaybe :: Sem (NonDet : r) a -> Sem r (Maybe a)
+ Polysemy.Output: ignoreOutput :: Sem (Output o : r) a -> Sem r a
+ Polysemy.Output: runOutputBatched :: forall o r a. Member (Output [o]) r => Int -> Sem (Output o : r) a -> Sem r a
+ Polysemy.Output: runOutputList :: forall o r a. Sem (Output o : r) a -> Sem r ([o], a)
+ Polysemy.Output: runOutputMonoid :: forall o m r a. Monoid m => (o -> m) -> Sem (Output o : r) a -> Sem r (m, a)
+ Polysemy.Reader: inputToReader :: Member (Reader i) r => Sem (Input i : r) a -> Sem r a
+ Polysemy.Resource: lowerResource :: forall r a. Member (Embed IO) r => (forall x. Sem r x -> IO x) -> Sem (Resource : r) a -> Sem r a
+ Polysemy.Resource: resourceToIO :: forall r a. LastMember (Embed IO) r => Sem (Resource : r) a -> Sem r a
+ Polysemy.State: evalLazyState :: s -> Sem (State s : r) a -> Sem r a
+ Polysemy.State: evalState :: s -> Sem (State s : r) a -> Sem r a
+ Polysemy.State: runStateIORef :: forall s r a. Member (Embed IO) r => IORef s -> Sem (State s : r) a -> Sem r a
+ Polysemy.Trace: ignoreTrace :: Sem (Trace : r) a -> Sem r a
+ Polysemy.Trace: outputToTrace :: (Show w, Member Trace r) => Sem (Output w : r) a -> Sem r a
+ Polysemy.Trace: runTraceList :: Sem (Trace : r) a -> Sem r ([String], a)
+ Polysemy.Trace: traceToIO :: Member (Embed IO) r => Sem (Trace : r) a -> Sem r a
+ Polysemy.Trace: traceToOutput :: Member (Output String) r => Sem (Trace : r) a -> Sem r a
+ Polysemy.Writer: outputToWriter :: Member (Writer o) r => Sem (Output o : r) a -> Sem r a
- Polysemy: runM :: Monad m => Sem '[Lift m] a -> m a
+ Polysemy: runM :: Monad m => Sem '[Embed m] a -> m a
- Polysemy: withLowerToIO :: LastMember (Lift IO) r => ((forall x. Sem r x -> IO x) -> IO () -> IO a) -> Sem r a
+ Polysemy: withLowerToIO :: LastMember (Embed IO) r => ((forall x. Sem r x -> IO x) -> IO () -> IO a) -> Sem r a
- Polysemy.Async: async :: forall r_atbd a_at2Y. MemberWithError Async r_atbd => Sem r_atbd a_at2Y -> Sem r_atbd (Async (Maybe a_at2Y))
+ Polysemy.Async: async :: forall r_atAp a_Xtr4. MemberWithError Async r_atAp => Sem r_atAp a_Xtr4 -> Sem r_atAp (Async (Maybe a_Xtr4))
- Polysemy.Async: await :: forall r_atbf a_at1P. MemberWithError Async r_atbf => Async a_at1P -> Sem r_atbf a_at1P
+ Polysemy.Async: await :: forall r_atAr a_atr4. MemberWithError Async r_atAr => Async a_atr4 -> Sem r_atAr a_atr4
- Polysemy.Error: catch :: forall e_argk r_arim a_argm. MemberWithError (Error e_argk) r_arim => Sem r_arim a_argm -> (e_argk -> Sem r_arim a_argm) -> Sem r_arim a_argm
+ Polysemy.Error: catch :: forall e_aruZ r_arwV a_arv1. MemberWithError (Error e_aruZ) r_arwV => Sem r_arwV a_arv1 -> (e_aruZ -> Sem r_arwV a_arv1) -> Sem r_arwV a_arv1
- Polysemy.Error: fromEitherM :: forall e m r a. (Member (Error e) r, Member (Lift m) r) => m (Either e a) -> Sem r a
+ Polysemy.Error: fromEitherM :: forall e m r a. (Member (Error e) r, Member (Embed m) r) => m (Either e a) -> Sem r a
- Polysemy.Error: throw :: forall e_argk r_arik a_argm. MemberWithError (Error e_argk) r_arik => e_argk -> Sem r_arik a_argm
+ Polysemy.Error: throw :: forall e_aruW r_arwT a_aruY. MemberWithError (Error e_aruW) r_arwT => e_aruW -> Sem r_arwT a_aruY
- Polysemy.Fixpoint: runFixpointM :: (MonadFix m, Member (Lift m) r) => (forall x. Sem r x -> m x) -> Sem (Fixpoint : r) a -> Sem r a
+ Polysemy.Fixpoint: runFixpointM :: (MonadFix m, Member (Embed m) r) => (forall x. Sem r x -> m x) -> Sem (Fixpoint : r) a -> Sem r a
- Polysemy.Input: input :: forall a_axV1 r_axVV. MemberWithError (Input a_axV1) r_axVV => Sem r_axVV a_axV1
+ Polysemy.Input: input :: forall i_az05 r_az0Y. MemberWithError (Input i_az05) r_az0Y => Sem r_az0Y i_az05
- Polysemy.Internal: runM :: Monad m => Sem '[Lift m] a -> m a
+ Polysemy.Internal: runM :: Monad m => Sem '[Embed m] a -> m a
- Polysemy.Internal.Forklift: Forklift :: MVar (Sem '[Lift IO] a) -> Union r (Sem r) a -> Forklift r
+ Polysemy.Internal.Forklift: Forklift :: MVar (Sem '[Embed IO] a) -> Union r (Sem r) a -> Forklift r
- Polysemy.Internal.Forklift: [responseMVar] :: Forklift r -> MVar (Sem '[Lift IO] a)
+ Polysemy.Internal.Forklift: [responseMVar] :: Forklift r -> MVar (Sem '[Embed IO] a)
- Polysemy.Internal.Forklift: runViaForklift :: LastMember (Lift IO) r => InChan (Forklift r) -> Sem r a -> Sem '[Lift IO] a
+ Polysemy.Internal.Forklift: runViaForklift :: LastMember (Embed IO) r => InChan (Forklift r) -> Sem r a -> Sem '[Embed IO] a
- Polysemy.Internal.Forklift: withLowerToIO :: LastMember (Lift IO) r => ((forall x. Sem r x -> IO x) -> IO () -> IO a) -> Sem r a
+ Polysemy.Internal.Forklift: withLowerToIO :: LastMember (Embed IO) r => ((forall x. Sem r x -> IO x) -> IO () -> IO a) -> Sem r a
- Polysemy.Internal.NonDet: Choose :: (Bool -> a) -> NonDet a
+ Polysemy.Internal.NonDet: Choose :: m a -> m a -> NonDet m a
- Polysemy.Internal.NonDet: Empty :: NonDet a
+ Polysemy.Internal.NonDet: Empty :: NonDet m a
- Polysemy.Internal.NonDet: data NonDet (m :: Type -> Type) a
+ Polysemy.Internal.NonDet: data NonDet m a
- Polysemy.Internal.TH.Common: getEffectMetadata :: Name -> Q (DatatypeInfo, [ConLiftInfo])
+ Polysemy.Internal.TH.Common: getEffectMetadata :: Name -> Q (Name, [ConLiftInfo])
- Polysemy.NonDet: Choose :: (Bool -> a) -> NonDet a
+ Polysemy.NonDet: Choose :: m a -> m a -> NonDet m a
- Polysemy.NonDet: Empty :: NonDet a
+ Polysemy.NonDet: Empty :: NonDet m a
- Polysemy.NonDet: data NonDet (m :: Type -> Type) a
+ Polysemy.NonDet: data NonDet m a
- Polysemy.Output: output :: forall o_axaQ r_axbJ. MemberWithError (Output o_axaQ) r_axbJ => o_axaQ -> Sem r_axbJ ()
+ Polysemy.Output: output :: forall o_ayeU r_ayfK. MemberWithError (Output o_ayeU) r_ayfK => o_ayeU -> Sem r_ayfK ()
- Polysemy.Reader: ask :: forall a_ayhL r_ayjj. MemberWithError (Reader a_ayhL) r_ayjj => Sem r_ayjj a_ayhL
+ Polysemy.Reader: ask :: forall i_azmP r_azom. MemberWithError (Reader i_azmP) r_azom => Sem r_azom i_azmP
- Polysemy.Reader: local :: forall i_ayhJ r_ayjk a_ayhL. MemberWithError (Reader i_ayhJ) r_ayjk => (i_ayhJ -> i_ayhJ) -> Sem r_ayjk a_ayhL -> Sem r_ayjk a_ayhL
+ Polysemy.Reader: local :: forall i_azmR r_azon a_azmT. MemberWithError (Reader i_azmR) r_azon => (i_azmR -> i_azmR) -> Sem r_azon a_azmT -> Sem r_azon a_azmT
- Polysemy.Resource: bracket :: forall r_auDq a_auDa c_auDb a_auBa. MemberWithError Resource r_auDq => Sem r_auDq a_auDa -> (a_auDa -> Sem r_auDq c_auDb) -> (a_auDa -> Sem r_auDq a_auBa) -> Sem r_auDq a_auBa
+ Polysemy.Resource: bracket :: forall r_avCT a_XvAG c_XvAI b_avAH. MemberWithError Resource r_avCT => Sem r_avCT a_XvAG -> (a_XvAG -> Sem r_avCT c_XvAI) -> (a_XvAG -> Sem r_avCT b_avAH) -> Sem r_avCT b_avAH
- Polysemy.Resource: bracketOnError :: forall r_auDu a_auDi c_auDj a_auBa. MemberWithError Resource r_auDu => Sem r_auDu a_auDi -> (a_auDi -> Sem r_auDu c_auDj) -> (a_auDi -> Sem r_auDu a_auBa) -> Sem r_auDu a_auBa
+ Polysemy.Resource: bracketOnError :: forall r_avCX a_XvAK c_XvAM b_avAL. MemberWithError Resource r_avCX => Sem r_avCX a_XvAK -> (a_XvAK -> Sem r_avCX c_XvAM) -> (a_XvAK -> Sem r_avCX b_avAL) -> Sem r_avCX b_avAL
- Polysemy.State: get :: forall a_aw3k r_aw4O. MemberWithError (State a_aw3k) r_aw4O => Sem r_aw4O a_aw3k
+ Polysemy.State: get :: forall s_ax2O r_ax4h. MemberWithError (State s_ax2O) r_ax4h => Sem r_ax4h s_ax2O
- Polysemy.State: put :: forall s_aw3i r_aw4P. MemberWithError (State s_aw3i) r_aw4P => s_aw3i -> Sem r_aw4P ()
+ Polysemy.State: put :: forall s_ax2Q r_ax4i. MemberWithError (State s_ax2Q) r_ax4i => s_ax2Q -> Sem r_ax4i ()
- Polysemy.Trace: trace :: forall r_ayGC. MemberWithError Trace r_ayGC => String -> Sem r_ayGC ()
+ Polysemy.Trace: trace :: forall r_azLF. MemberWithError Trace r_azLF => String -> Sem r_azLF ()
- Polysemy.Writer: listen :: forall o_azaI r_azdb a_azcP. MemberWithError (Writer o_azaI) r_azdb => Sem r_azdb a_azcP -> Sem r_azdb (o_azaI, a_azcP)
+ Polysemy.Writer: listen :: forall o_aAfx r_aAhV a_XAfA. MemberWithError (Writer o_aAfx) r_aAhV => Sem r_aAhV a_XAfA -> Sem r_aAhV (o_aAfx, a_XAfA)
- Polysemy.Writer: pass :: forall o_azaI r_azdd a_azaK. MemberWithError (Writer o_azaI) r_azdd => Sem r_azdd (o_azaI -> o_azaI, a_azaK) -> Sem r_azdd a_azaK
+ Polysemy.Writer: pass :: forall o_aAfB r_aAhX a_aAfC. MemberWithError (Writer o_aAfB) r_aAhX => Sem r_aAhX (o_aAfB -> o_aAfB, a_aAfC) -> Sem r_aAhX a_aAfC
- Polysemy.Writer: tell :: forall o_azaI r_azd9. MemberWithError (Writer o_azaI) r_azd9 => o_azaI -> Sem r_azd9 ()
+ Polysemy.Writer: tell :: forall o_aAfv r_aAhT. MemberWithError (Writer o_aAfv) r_aAhT => o_aAfv -> Sem r_aAhT ()

Files

ChangeLog.md view
@@ -1,12 +1,53 @@ # Changelog for polysemy +## 1.0.0.0 (2019-07-24)++### Breaking Changes++- Renamed `Lift`  to `Embed` (thanks to @googleson78)+- Renamed `runAsyncInIO` to `lowerAsync`+- Renamed `runAsync` to `asyncToIO`+- Renamed `runBatchOutput` to `runOutputBatched`+- Renamed `runConstInput` to `runInputConst`+- Renamed `runEmbed` to `runEmbedded` (thanks to @googleson78)+- Renamed `runEmbedded` to `lowerEmbedded`+- Renamed `runErrorAsAnother` to `mapError`+- Renamed `runErrorInIO` to `lowerError`+- Renamed `runFoldMapOutput` to `runOutputMonoid`+- Renamed `runIO` to `embedToMonadIO`+- Renamed `runIgnoringOutput` to `ignoreOutput`+- Renamed `runIgnoringTrace` to `ignoreTrace`+- Renamed `runInputAsReader` to `inputToReader`+- Renamed `runListInput` to `runInputList`+- Renamed `runMonadicInput` to `runInputSem`+- Renamed `runOutputAsList` to `runOutputList`+- Renamed `runOutputAsTrace` to `outputToTrace`+- Renamed `runOutputAsWriter` to `outputToWriter`+- Renamed `runResourceBase` to `resourceToIO`+- Renamed `runResourceInIO` to `lowerResource`+- Renamed `runStateInIORef` to `runStateIORef`+- Renamed `runTraceAsList` to `runTraceList`+- Renamed `runTraceAsOutput` to `traceToOutput`+- Renamed `runTraceIO` to `traceToIO`+- Renamed `sendM` to `embed` (thanks to @googleson78)+- The `NonDet` effect will no longer perform effects in untaken branches (thanks to @KingoftheHomeless)++### Other Changes++- Added `evalState` and `evalLazyState`+- Added `runNonDetMaybe` (thanks to @KingoftheHomeless)+- Added `nonDetToMaybe` (thanks to @KingoftheHomeless)+- Haddock documentation for smart constructors generated via `makeSem` will no+    longer have weird variable names (thanks to @TheMatten)++ ## 0.7.0.0 (2019-07-08)  ### Breaking Changes -- Added a `Pass` constructor to `Writer`-- Fixed a bug in `runWriter` where the MTL semantics wouldn't be respected-- Removed the `Censor` constructor of `Writer`+- Added a `Pass` constructor to `Writer` (thanks to @KingoftheHomeless)+- Fixed a bug in `runWriter` where the MTL semantics wouldn't be respected (thanks to @KingoftheHomeless)+- Removed the `Censor` constructor of `Writer` (thanks to @KingoftheHomeless) - Renamed `Yo` to `Weaving` - Changed the visible type applications for `asks`, `gets`, and `runErrorAsAnother` 
README.md view
@@ -91,15 +91,15 @@  makeSem ''Teletype -runTeletypeIO :: Member (Lift IO) r => Sem (Teletype ': r) a -> Sem r a-runTeletypeIO = interpret $ \case-  ReadTTY      -> sendM getLine-  WriteTTY msg -> sendM $ putStrLn msg+teletypeToIO :: Member (Lift IO) r => Sem (Teletype ': r) a -> Sem r a+teletypeToIO = interpret $ \case+  ReadTTY      -> embed getLine+  WriteTTY msg -> embed $ putStrLn msg  runTeletypePure :: [String] -> Sem (Teletype ': r) a -> Sem r ([String], a) runTeletypePure i-  = runFoldMapOutput pure  -- For each WriteTTY in our program, consume an output by appending it to the list in a ([String], a)-  . runListInput i         -- Treat each element of our list of strings as a line of input+  = runOutputMonoid pure  -- For each WriteTTY in our program, consume an output by appending it to the list in a ([String], a)+  . runInputList i         -- Treat each element of our list of strings as a line of input   . reinterpret2 \case     -- Reinterpret our effect in terms of Input and Output       ReadTTY -> maybe "" id <$> input       WriteTTY msg -> output msg@@ -120,13 +120,9 @@ pureOutput :: [String] -> [String] pureOutput = fst . run . echoPure --- Now let's do things-echoIO :: Sem '[Lift IO] ()-echoIO = runTeletypeIO echo- -- echo forever main :: IO ()-main = runM echoIO+main = runM . teletypeToIO $ echo ```  @@ -157,7 +153,7 @@             _             -> writeTTY input >> writeTTY "no exceptions"  main :: IO (Either CustomException ())-main = (runM .@ runResourceInIO .@@ runErrorInIO @CustomException) . runTeletypeIO $ program+main = (runM .@ lowerResource .@@ lowerError @CustomException) . teletypeToIO $ program ```  Easy.@@ -218,3 +214,20 @@     - TypeOperators     - TypeFamilies ```++## Stellar Engineering - Aligning the stars to optimize `polysemy` away++Several things need to be in place to fully realize our performance goals: ++- GHC Version+  - GHC 8.9++- Your code+  - The module you want to be optimized needs to import `Polysemy.Internal` somewhere in its dependency tree (sufficient to `import Polysemy`)+- GHC Flags+  - `-O` or `-O2`+  - `-flate-specialise` (this should be automatically turned on by the plugin, but it's worth mentioning)+- Plugin+  - `-fplugin=Polysemy.Plugin`+- Additional concerns:+  - additional core passes (turned on by the plugin)+
bench/Poly.hs view
@@ -36,13 +36,13 @@     :: Sem '[ State Bool             , Error Bool             , Resource-            , Lift IO+            , Embed IO             ] Bool prog = catch @Bool (throw True) (pure . not)  zoinks :: IO (Either Bool Bool) zoinks = fmap (fmap snd)-       . (runM .@ runResourceInIO .@@ runErrorInIO)+       . (runM .@ lowerResource .@@ lowerError)        . runState False        $ prog @@ -54,8 +54,8 @@  runConsoleBoring :: [String] -> Sem (Console ': r) a -> Sem r ([String], a) runConsoleBoring inputs-  = runFoldMapOutput (:[])-  . runListInput inputs+  = runOutputMonoid (:[])+  . runInputList inputs   . reinterpret2   (\case       ReadLine -> maybe "" id <$> input
polysemy.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: e22afd49cd8b82cdc69be962d872539c65eedc43a2978aa7a0652b40dd7db105+-- hash: f543f8ca2c4f661f0b6702fb6ec6d7db075660d19bf550e50a04e64c56826913  name:           polysemy-version:        0.7.0.0+version:        1.0.0.0 synopsis:       Higher-order, low-boilerplate, zero-cost free monads. description:    Please see the README on GitHub at <https://github.com/isovector/polysemy#readme> category:       Language@@ -41,6 +41,8 @@   exposed-modules:       Polysemy       Polysemy.Async+      Polysemy.Embed+      Polysemy.Embed.Type       Polysemy.Error       Polysemy.Fixpoint       Polysemy.Input@@ -51,7 +53,6 @@       Polysemy.Internal.Fixpoint       Polysemy.Internal.Forklift       Polysemy.Internal.Kind-      Polysemy.Internal.Lift       Polysemy.Internal.NonDet       Polysemy.Internal.Tactics       Polysemy.Internal.TH.Common@@ -82,6 +83,7 @@     , th-abstraction >=0.3.1.0 && <0.4     , transformers >=0.5.2.0 && <0.6     , type-errors >=0.2.0.0+    , type-errors-pretty >=0.0.0.0 && <0.1     , unagi-chan >=0.4.0.0 && <0.5   if impl(ghc < 8.6)     default-extensions: MonadFailDesugaring TypeInType@@ -141,6 +143,7 @@     , th-abstraction >=0.3.1.0 && <0.4     , transformers >=0.5.2.0 && <0.6     , type-errors >=0.2.0.0+    , type-errors-pretty >=0.0.0.0 && <0.1     , unagi-chan >=0.4.0.0 && <0.5   if impl(ghc < 8.6)     default-extensions: MonadFailDesugaring TypeInType@@ -173,6 +176,7 @@     , th-abstraction >=0.3.1.0 && <0.4     , transformers >=0.5.2.0 && <0.6     , type-errors >=0.2.0.0+    , type-errors-pretty >=0.0.0.0 && <0.1     , unagi-chan >=0.4.0.0 && <0.5   if impl(ghc < 8.6)     default-extensions: MonadFailDesugaring TypeInType
src/Polysemy.hs view
@@ -10,8 +10,8 @@   , runM    -- * Interoperating With Other Monads-  , Lift (..)-  , sendM+  , Embed (..)+  , embed      -- * Lifting   , raise
src/Polysemy/Async.hs view
@@ -9,8 +9,8 @@   , await      -- * Interpretations-  , runAsync-  , runAsyncInIO+  , asyncToIO+  , lowerAsync   ) where  import qualified Control.Concurrent.Async as A@@ -32,53 +32,52 @@ makeSem ''Async  --------------------------------------------------------------------------------- | A more flexible --- though less performant ---  version of 'runAsyncInIO'.+-- | A more flexible --- though less performant ---  version of 'lowerAsync'. -- -- This function is capable of running 'Async' effects anywhere within an -- effect stack, without relying on an explicit function to lower it into 'IO'. -- Notably, this means that 'Polysemy.State.State' effects will be consistent -- in the presence of 'Async'. ----- @since 0.5.0.0-runAsync-    :: LastMember (Lift IO) r+-- @since 1.0.0.0+asyncToIO+    :: LastMember (Embed IO) r     => Sem (Async ': r) a     -> Sem r a-runAsync m = withLowerToIO $ \lower _ -> lower $+asyncToIO m = withLowerToIO $ \lower _ -> lower $   interpretH     ( \case         Async a -> do           ma  <- runT a           ins <- getInspectorT-          fa  <- sendM $ A.async $ lower $ runAsync ma+          fa  <- embed $ A.async $ lower $ asyncToIO ma           pureT $ fmap (inspect ins) fa -        Await a -> pureT =<< sendM (A.wait a)+        Await a -> pureT =<< embed (A.wait a)     )  m-{-# INLINE runAsync #-}+{-# INLINE asyncToIO #-}   ------------------------------------------------------------------------------ -- | Run an 'Async' effect via in terms of 'A.async'. -------- @since 0.5.0.0-runAsyncInIO-    :: Member (Lift IO) r+-- @since 1.0.0.0+lowerAsync+    :: Member (Embed IO) r     => (forall x. Sem r x -> IO x)        -- ^ Strategy for lowering a 'Sem' action down to 'IO'. This is likely        -- some combination of 'runM' and other interpreters composed via '.@'.     -> Sem (Async ': r) a     -> Sem r a-runAsyncInIO lower m = interpretH+lowerAsync lower m = interpretH     ( \case         Async a -> do           ma  <- runT a           ins <- getInspectorT-          fa  <- sendM $ A.async $ lower $ runAsyncInIO lower ma+          fa  <- embed $ A.async $ lower $ lowerAsync lower ma           pureT $ fmap (inspect ins) fa -        Await a -> pureT =<< sendM (A.wait a)+        Await a -> pureT =<< embed (A.wait a)     )  m-{-# INLINE runAsyncInIO #-}+{-# INLINE lowerAsync #-} 
+ src/Polysemy/Embed.hs view
@@ -0,0 +1,29 @@+{-# LANGUAGE TemplateHaskell #-}++module Polysemy.Embed+  ( -- * Effect+    Embed (..)++    -- * Actions+  , embed++    -- * Interpretations+  , runEmbedded+  ) where++import Polysemy+import Polysemy.Embed.Type (Embed (..))++------------------------------------------------------------------------------+-- | Given a natural transform from @m1@ to @m2@+-- run a @Embed m1@ effect by transforming it into a @Embed m2@ effect.+--+-- @since 1.0.0.0+runEmbedded+    :: forall m1 m2 r a+     . Member (Embed m2) r+    => (forall x. m1 x -> m2 x)+    -> Sem (Embed m1 ': r) a+    -> Sem r a+runEmbedded f = interpret $ embed . f . unEmbed+{-# INLINE runEmbedded #-}
+ src/Polysemy/Embed/Type.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE NoPolyKinds #-}++{-# OPTIONS_HADDOCK not-home #-}++module Polysemy.Embed.Type+  ( -- * Effect+    Embed (..)+  ) where++import Data.Kind+++------------------------------------------------------------------------------+-- | An effect which allows a regular 'Monad' @m@ into the 'Polysemy.Sem'+-- ecosystem. Monadic actions in @m@ can be lifted into 'Polysemy.Sem' via+-- 'Polysemy.embed'.+--+-- For example, you can use this effect to lift 'IO' actions directly into+-- 'Polysemy.Sem':+--+-- @+-- 'Polysemy.embed' (putStrLn "hello") :: 'Polysemy.Member' ('Polysemy.Embed' IO) r => 'Polysemy.Sem' r ()+-- @+--+-- That being said, you lose out on a significant amount of the benefits of+-- 'Polysemy.Sem' by using 'Polysemy.embed' directly in application code; doing+-- so will tie your application code directly to the underlying monad, and+-- prevent you from interpreting it differently. For best results, only use+-- 'Embed' in your effect interpreters.+--+-- Consider using 'Polysemy.Trace.trace' and 'Polysemy.Trace.traceToIO' as+-- a substitute for using 'putStrLn' directly.+--+-- @since 1.0.0.0+newtype Embed m (z :: Type -> Type) a where+  Embed :: { unEmbed :: m a } -> Embed m z a
src/Polysemy/Error.hs view
@@ -12,8 +12,8 @@      -- * Interpretations   , runError-  , runErrorAsAnother-  , runErrorInIO+  , mapError+  , lowerError   ) where  import qualified Control.Exception as X@@ -51,18 +51,18 @@   --------------------------------------------------------------------------------- | A combinator doing 'sendM' and 'fromEither' at the same time. Useful for+-- | A combinator doing 'embed' and 'fromEither' at the same time. Useful for -- interoperating with 'IO'. -- -- @since 0.5.1.0 fromEitherM     :: forall e m r a      . ( Member (Error e) r-       , Member (Lift m) r+       , Member (Embed m) r        )     => m (Either e a)     -> Sem r a-fromEitherM = fromEither <=< sendM+fromEitherM = fromEither <=< embed   ------------------------------------------------------------------------------@@ -96,14 +96,14 @@ -- | Transform one 'Error' into another. This function can be used to aggregate -- multiple errors into a single type. ----- @since 0.2.2.0-runErrorAsAnother+-- @since 1.0.0.0+mapError   :: forall e1 e2 r a    . Member (Error e2) r   => (e1 -> e2)   -> Sem (Error e1 ': r) a   -> Sem r a-runErrorAsAnother f = interpretH $ \case+mapError f = interpretH $ \case   Throw e -> throw $ f e   Catch action handler -> do     a  <- runT action@@ -118,7 +118,7 @@         case mx' of           Right x -> pure x           Left e' -> throw $ f e'-{-# INLINE runErrorAsAnother #-}+{-# INLINE mapError #-}   newtype WrappedExc e = WrappedExc { unwrapExc :: e }@@ -133,9 +133,11 @@ ------------------------------------------------------------------------------ -- | Run an 'Error' effect as an 'IO' 'X.Exception'. This interpretation is -- significantly faster than 'runError', at the cost of being less flexible.-runErrorInIO+--+-- @since 1.0.0.0+lowerError     :: ( Typeable e-       , Member (Lift IO) r+       , Member (Embed IO) r        )     => (∀ x. Sem r x -> IO x)        -- ^ Strategy for lowering a 'Sem' action down to 'IO'. This is@@ -143,30 +145,30 @@        -- '.@'.     -> Sem (Error e ': r) a     -> Sem r (Either e a)-runErrorInIO lower-    = sendM+lowerError lower+    = embed     . fmap (first unwrapExc)     . X.try     . (lower .@ runErrorAsExc)-{-# INLINE runErrorInIO #-}+{-# INLINE lowerError #-}   -- TODO(sandy): Can we use the new withLowerToIO machinery for this? runErrorAsExc     :: forall e r a. ( Typeable e-       , Member (Lift IO) r+       , Member (Embed IO) r        )     => (∀ x. Sem r x -> IO x)     -> Sem (Error e ': r) a     -> Sem r a runErrorAsExc lower = interpretH $ \case-  Throw e -> sendM $ X.throwIO $ WrappedExc e+  Throw e -> embed $ X.throwIO $ WrappedExc e   Catch try handle -> do     is <- getInitialStateT     t  <- runT try     h  <- bindT handle     let runIt = lower . runErrorAsExc lower-    sendM $ X.catch (runIt t) $ \(se :: WrappedExc e) ->+    embed $ X.catch (runIt t) $ \(se :: WrappedExc e) ->       runIt $ h $ unwrapExc se <$ is {-# INLINE runErrorAsExc #-} 
src/Polysemy/Fixpoint.hs view
@@ -29,7 +29,7 @@ -- | Run a 'Fixpoint' effect in terms of an underlying 'MonadFix' instance. runFixpointM     :: ( MonadFix m-       , Member (Lift m) r+       , Member (Embed m) r        )     => (∀ x. Sem r x -> m x)     -> Sem (Fixpoint ': r) a@@ -37,5 +37,5 @@ runFixpointM lower = interpretH $ \case   Fixpoint mf -> do     c <- bindT mf-    sendM $ mfix $ lower . runFixpointM lower . c+    embed $ mfix $ lower . runFixpointM lower . c 
src/Polysemy/IO.hs view
@@ -2,19 +2,18 @@  module Polysemy.IO   ( -- * Interpretations-    runIO-  , runEmbedded+    embedToMonadIO+  , lowerEmbedded   ) where  import Control.Monad.IO.Class import Polysemy+import Polysemy.Embed import Polysemy.Internal import Polysemy.Internal.Union   --------------------------------------------------------------------------------- | __If you trying to run 'Sem' in 'IO', the function you want is 'runM'.__--- -- The 'MonadIO' class is conceptually an interpretation of 'IO' to some -- other monad. This function reifies that intuition, by transforming an 'IO' -- effect into some other 'MonadIO'.@@ -22,52 +21,53 @@ -- This function is especially useful when using the 'MonadIO' instance for -- 'Sem' instance. ----- Make sure to type-apply the desired 'MonadIO' instance when using 'runIO'.+-- Make sure to type-apply the desired 'MonadIO' instance when using+-- 'embedToMonadIO'. ----- @since 0.1.1.0+-- @since 1.0.0.0 -- -- ==== Example -- -- @ -- foo :: PandocIO ()--- foo = 'runM' . 'runIO' @PandocIO $ do+-- foo = 'runM' . 'embedToMonadIO' @PandocIO $ do --   'liftIO' $ putStrLn "hello from polysemy" -- @ ---runIO+embedToMonadIO     :: forall m r a      . ( MonadIO m-       , Member (Lift m) r+       , Member (Embed m) r        )-    => Sem (Lift IO ': r) a+    => Sem (Embed IO ': r) a     -> Sem r a-runIO = interpret $ sendM . liftIO @m . unLift-{-# INLINE runIO #-}+embedToMonadIO = runEmbedded $ liftIO @m+{-# INLINE embedToMonadIO #-}   --------------------------------------------------------------------------------- | Given some @'MonadIO' m@, interpret all @'Lift' m@ actions in that monad+-- | Given some @'MonadIO' m@, interpret all @'Embed' m@ actions in that monad -- at once. This is useful for interpreting effects like databases, which use -- their own monad for describing actions. -- -- This function creates a thread, and so should be compiled with @-threaded@. ----- @since 0.6.0.0-runEmbedded+-- @since 1.0.0.0+lowerEmbedded     :: ( MonadIO m-       , LastMember (Lift IO) r+       , LastMember (Embed IO) r        )     => (forall x. m x -> IO x)  -- ^ The means of running this monad.-    -> Sem (Lift m ': r) a+    -> Sem (Embed m ': r) a     -> Sem r a-runEmbedded run_m (Sem m) = withLowerToIO $ \lower _ ->+lowerEmbedded run_m (Sem m) = withLowerToIO $ \lower _ ->   run_m $ m $ \u ->     case decomp u of       Left x -> liftIO               . lower               . liftSem-              $ hoist (runEmbedded run_m) x+              $ hoist (lowerEmbedded run_m) x -      Right (Weaving (Lift wd) s _ y _) ->+      Right (Weaving (Embed wd) s _ y _) ->         fmap y $ fmap (<$ s) wd 
src/Polysemy/Input.hs view
@@ -8,9 +8,9 @@   , input      -- * Interpretations-  , runConstInput-  , runListInput-  , runMonadicInput+  , runInputConst+  , runInputList+  , runInputSem   ) where  import Data.Foldable (for_)@@ -29,33 +29,33 @@  ------------------------------------------------------------------------------ -- | Run an 'Input' effect by always giving back the same value.-runConstInput :: i -> Sem (Input i ': r) a -> Sem r a-runConstInput c = interpret $ \case+runInputConst :: i -> Sem (Input i ': r) a -> Sem r a+runInputConst c = interpret $ \case   Input -> pure c-{-# INLINE runConstInput #-}+{-# INLINE runInputConst #-}   ------------------------------------------------------------------------------ -- | Run an 'Input' effect by providing a different element of a list each -- time. Returns 'Nothing' after the list is exhausted.-runListInput+runInputList     :: [i]     -> Sem (Input (Maybe i) ': r) a     -> Sem r a-runListInput is = fmap snd . runState is . reinterpret+runInputList is = fmap snd . runState is . reinterpret   (\case       Input -> do         s <- gets uncons         for_ s $ put . snd         pure $ fmap fst s   )-{-# INLINE runListInput #-}+{-# INLINE runInputList #-}   ------------------------------------------------------------------------------ -- | Runs an 'Input' effect by evaluating a monadic action for each request.-runMonadicInput :: forall i r a. Sem r i -> Sem (Input i ': r) a -> Sem r a-runMonadicInput m = interpret $ \case+runInputSem :: forall i r a. Sem r i -> Sem (Input i ': r) a -> Sem r a+runInputSem m = interpret $ \case   Input -> m-{-# INLINE runMonadicInput #-}+{-# INLINE runInputSem #-} 
src/Polysemy/Internal.hs view
@@ -11,14 +11,14 @@   , Member   , Members   , send-  , sendM+  , embed   , run   , runM   , raise   , raiseUnder   , raiseUnder2   , raiseUnder3-  , Lift (..)+  , Embed (..)   , usingSem   , liftSem   , hoistSem@@ -34,12 +34,17 @@ import Data.Functor.Identity import Data.Kind import Polysemy.Internal.Fixpoint-import Polysemy.Internal.Lift+import Polysemy.Embed.Type import Polysemy.Internal.NonDet import Polysemy.Internal.PluginLookup import Polysemy.Internal.Union  +-- $setup+-- >>> import Data.Function+-- >>> import Polysemy.State+-- >>> import Polysemy.Error+ ------------------------------------------------------------------------------ -- | The 'Sem' monad handles computations of arbitrary extensible effects. -- A value of type @Sem r@ describes a program with the capabilities of@@ -54,11 +59,11 @@ -- interpretations (and others that you might add) may be used interchangably -- without needing to write any newtypes or 'Monad' instances. The only -- change needed to swap interpretations is to change a call from--- 'Polysemy.Error.runError' to 'Polysemy.Error.runErrorInIO'.+-- 'Polysemy.Error.runError' to 'Polysemy.Error.lowerError'. -- -- The effect stack @r@ can contain arbitrary other monads inside of it. These--- monads are lifted into effects via the 'Lift' effect. Monadic values can be--- lifted into a 'Sem' via 'sendM'.+-- monads are lifted into effects via the 'Embed' effect. Monadic values can be+-- lifted into a 'Sem' via 'embed'. -- -- A 'Sem' can be interpreted as a pure value (via 'run') or as any -- traditional 'Monad' (via 'runM'). Each effect @E@ comes equipped with some@@ -72,8 +77,55 @@ -- is the order in which you call the interpreters that determines the -- monomorphic representation of the @r@ parameter. --+-- Order of interpreters can be important - it determines behaviour of effects+-- that manipulate state or change control flow. For example, when+-- interpreting this action:+--+-- >>> :{+--   example :: Members '[State String, Error String] r => Sem r String+--   example = do+--     put "start"+--     let throwing, catching :: Members '[State String, Error String] r => Sem r String+--         throwing = do+--           modify (++"-throw")+--           throw "error"+--           get+--         catching = do+--           modify (++"-catch")+--           get+--     catch @String throwing (\ _ -> catching)+-- :}+--+-- when handling 'Polysemy.Error.Error' first, state is preserved after error+-- occurs:+--+-- >>> :{+--   example+--     & runError+--     & fmap (either id id)+--     & evalState ""+--     & runM+--     & (print =<<)+-- :}+-- "start-throw-catch"+--+-- while handling 'Polysemy.State.State' first discards state in such cases:+--+-- >>> :{+--   example+--     & evalState ""+--     & runError+--     & fmap (either id id)+--     & runM+--     & (print =<<)+-- :}+-- "start-catch"+--+-- A good rule of thumb is to handle effects which should have \"global\"+-- behaviour over other effects later in the chain.+-- -- After all of your effects are handled, you'll be left with either--- a @'Sem' '[] a@ or a @'Sem' '[ 'Lift' m ] a@ value, which can be+-- a @'Sem' '[] a@ or a @'Sem' '[ 'Embed' m ] a@ value, which can be -- consumed respectively by 'run' and 'runM'. -- -- ==== Examples@@ -211,10 +263,7 @@ instance (Member NonDet r) => Alternative (Sem r) where   empty = send Empty   {-# INLINE empty #-}-  a <|> b = do-    send (Choose id) >>= \case-      False -> a-      True  -> b+  a <|> b = send (Choose a b)   {-# INLINE (<|>) #-}  -- | @since 0.2.1.0@@ -230,9 +279,9 @@ ------------------------------------------------------------------------------ -- | This instance will only lift 'IO' actions. If you want to lift into some -- other 'MonadIO' type, use this instance, and handle it via the--- 'Polysemy.IO.runIO' interpretation.-instance (Member (Lift IO) r) => MonadIO (Sem r) where-  liftIO = sendM+-- 'Polysemy.IO.embedToMonadIO' interpretation.+instance (Member (Embed IO) r) => MonadIO (Sem r) where+  liftIO = embed   {-# INLINE liftIO #-}  instance Member Fixpoint r => MonadFix (Sem r) where@@ -300,7 +349,7 @@   --------------------------------------------------------------------------------- | Lift an effect into a 'Sem'. This is used primarily via+-- | Embed an effect into a 'Sem'. This is used primarily via -- 'Polysemy.makeSem' to implement smart constructors. send :: Member e r => e (Sem r) a -> Sem r a send = liftSem . inj@@ -308,10 +357,12 @@   --------------------------------------------------------------------------------- | Lift a monadic action @m@ into 'Sem'.-sendM :: Member (Lift m) r => m a -> Sem r a-sendM = send . Lift-{-# INLINE sendM #-}+-- | Embed a monadic action @m@ in 'Sem'.+--+-- @since 1.0.0.0+embed :: Member (Embed m) r => m a -> Sem r a+embed = send . Embed+{-# INLINE embed #-}   ------------------------------------------------------------------------------@@ -324,11 +375,11 @@ ------------------------------------------------------------------------------ -- | Lower a 'Sem' containing only a single lifted 'Monad' into that -- monad.-runM :: Monad m => Sem '[Lift m] a -> m a+runM :: Monad m => Sem '[Embed m] a -> m a runM (Sem m) = m $ \z ->   case extract z of     Weaving e s _ f _ -> do-      a <- unLift e+      a <- unEmbed e       pure $ f $ a <$ s {-# INLINE runM #-} @@ -336,13 +387,13 @@ ------------------------------------------------------------------------------ -- | Some interpreters need to be able to lower down to the base monad (often -- 'IO') in order to function properly --- some good examples of this are--- 'Polysemy.Error.runErrorInIO' and 'Polysemy.Resource.runResourceInIO'.+-- 'Polysemy.Error.lowerError' and 'Polysemy.Resource.lowerResource'. -- -- However, these interpreters don't compose particularly nicely; for example,--- to run 'Polysemy.Resource.runResourceInIO', you must write:+-- to run 'Polysemy.Resource.lowerResource', you must write: -- -- @--- runM . runErrorInIO runM+-- runM . lowerError runM -- @ -- -- Notice that 'runM' is duplicated in two places here. The situation gets@@ -352,7 +403,7 @@ -- Instead, '.@' performs the composition we'd like. The above can be written as -- -- @--- (runM .@ runErrorInIO)+-- (runM .@ lowerError) -- @ -- -- The parentheses here are important; without them you'll run into operator@@ -377,7 +428,7 @@  ------------------------------------------------------------------------------ -- | Like '.@', but for interpreters which change the resulting type --- eg.--- 'Polysemy.Error.runErrorInIO'.+-- 'Polysemy.Error.lowerError'. (.@@)     :: Monad m     => (∀ x. Sem r x -> m x)
src/Polysemy/Internal/CustomErrors.hs view
@@ -17,10 +17,11 @@  import Data.Kind import Fcf-import GHC.TypeLits+import GHC.TypeLits (Symbol) import Polysemy.Internal.Kind import Polysemy.Internal.CustomErrors.Redefined import Type.Errors hiding (IfStuck, WhenStuck, UnlessStuck)+import Type.Errors.Pretty (type (<>), type (%))   ------------------------------------------------------------------------------@@ -37,9 +38,7 @@   -- TODO(sandy): Put in type-errors-type ShowTypeBracketed t = 'Text "("-                     ':<>: 'ShowType t-                     ':<>: 'Text ")"+type ShowTypeBracketed t = "(" <> t <> ")"   ------------------------------------------------------------------------------@@ -67,24 +66,15 @@                            (r :: EffectRow)                            (e :: k)                            (t :: Effect)-                           (vs :: [Type]) =-        ( 'Text "Ambiguous use of effect '"-    ':<>: 'ShowType e-    ':<>: 'Text "'"-    ':$$: 'Text "Possible fix:"-    ':$$: 'Text "  add (Member ("-    ':<>: 'ShowType t-    ':<>: 'Text ") "-    ':<>: ShowRQuoted rstate r-    ':<>: 'Text ") to the context of "-    ':$$: 'Text "    the type signature"-    ':$$: 'Text "If you already have the constraint you want, instead"-    ':$$: 'Text "  add a type application to specify"-    ':$$: 'Text "    "-    ':<>: PrettyPrintList vs-    ':<>: 'Text " directly, or activate polysemy-plugin which"-    ':$$: 'Text "      can usually infer the type correctly."-        )+                           (vs :: [Type])+  = "Ambiguous use of effect '" <> e <> "'"+  % "Possible fix:"+  % "  add (Member (" <> t <> ") " <> ShowRQuoted rstate r <> ") to the context of "+  % "    the type signature"+  % "If you already have the constraint you want, instead"+  % "  add a type application to specify"+  % "    " <> PrettyPrintList vs <> " directly, or activate polysemy-plugin which"+  % "      can usually infer the type correctly."  type AmbiguousSend r e =       (IfStuck r@@ -110,18 +100,10 @@    AmbiguousSendError rstate r e =     TypeError-        ( 'Text "Could not deduce: (Member "-    ':<>: 'ShowType e-    ':<>: 'Text " "-    ':<>: ShowRQuoted rstate r-    ':<>: 'Text ") "-    ':$$: 'Text "Fix:"-    ':$$: 'Text "  add (Member "-    ':<>: 'ShowType e-    ':<>: 'Text " "-    ':<>: 'ShowType r-    ':<>: 'Text ") to the context of"-    ':$$: 'Text "    the type signature"+        ( "Could not deduce: (Member " <>  e <> " " <> ShowRQuoted rstate r <> ") "+        % "Fix:"+        % "  add (Member " <>  e <> " " <> r <> ") to the context of"+        % "    the type signature"         )  @@ -129,16 +111,10 @@ type instance Eval (FirstOrderErrorFcf e fn) = $(te[t|     UnlessPhantom         (e PHANTOM)-        ( 'Text "'"-    ':<>: 'ShowType e-    ':<>: 'Text "' is higher-order, but '"-    ':<>: 'Text fn-    ':<>: 'Text "' can help only"-    ':$$: 'Text "with first-order effects."-    ':$$: 'Text "Fix:"-    ':$$: 'Text "  use '"-    ':<>: 'Text fn-    ':<>: 'Text "H' instead."+        ( "'" <> e <> "' is higher-order, but '" <> fn <> "' can help only"+        % "with first-order effects."+        % "Fix:"+        % "  use '" <> fn <> "H' instead."         ) |])  ------------------------------------------------------------------------------@@ -150,19 +126,13 @@ ------------------------------------------------------------------------------ -- | Unhandled effects type UnhandledEffectMsg e-      = 'Text "Unhandled effect '"-  ':<>: 'ShowType e-  ':<>: 'Text "'"-  ':$$: 'Text "Probable fix:"-  ':$$: 'Text "  add an interpretation for '"-  ':<>: 'ShowType e-  ':<>: 'Text "'"+  = "Unhandled effect '" <> e <> "'"+  % "Probable fix:"+  % "  add an interpretation for '" <> e <> "'"  type CheckDocumentation e-      = 'Text "  If you are looking for inspiration, try consulting"-  ':$$: 'Text "    the documentation for module '"-  ':<>: 'Text (DefiningModuleForEffect e)-  ':<>: 'Text "'"+  = "  If you are looking for inspiration, try consulting"+  % "    the documentation for module '" <> DefiningModuleForEffect e <> "'"  type family UnhandledEffect e where   UnhandledEffect e =@@ -173,4 +143,3 @@  data DoError :: ErrorMessage -> Exp k type instance Eval (DoError a) = TypeError a-
src/Polysemy/Internal/Forklift.hs view
@@ -19,7 +19,7 @@ -- -- @since 0.5.0.0 data Forklift r = forall a. Forklift-  { responseMVar :: MVar (Sem '[Lift IO] a)+  { responseMVar :: MVar (Sem '[Embed IO] a)   , request      :: Union r (Sem r) a   } @@ -30,13 +30,13 @@ -- -- @since 0.5.0.0 runViaForklift-    :: LastMember (Lift IO) r+    :: LastMember (Embed IO) r     => InChan (Forklift r)     -> Sem r a-    -> Sem '[Lift IO] a+    -> Sem '[Embed IO] a runViaForklift chan (Sem m) = Sem $ \k -> m $ \u -> do   case decompLast u of-    Left x -> usingSem k $ join $ sendM $ do+    Left x -> usingSem k $ join $ embed $ do       mvar <- newEmptyMVar       writeChan chan $ Forklift mvar x       takeMVar mvar@@ -53,29 +53,29 @@ -- -- @since 0.5.0.0 withLowerToIO-    :: LastMember (Lift IO) r+    :: LastMember (Embed IO) r     => ((forall x. Sem r x -> IO x) -> IO () -> IO a)        -- ^ A lambda that takes the lowering function, and a finalizing 'IO'        -- action to mark a the forked thread as being complete. The finalizing        -- action need not be called.     -> Sem r a withLowerToIO action = do-  (inchan, outchan) <- sendM newChan-  signal <- sendM newEmptyMVar+  (inchan, outchan) <- embed newChan+  signal <- embed newEmptyMVar -  res <- sendM $ A.async $ do+  res <- embed $ A.async $ do     a <- action (runM . runViaForklift inchan)                 (putMVar signal ())     putMVar signal ()     pure a    let me = do-        raced <- sendM $ A.race (takeMVar signal) $ readChan outchan+        raced <- embed $ A.race (takeMVar signal) $ readChan outchan         case raced of-          Left () -> sendM $ A.wait res+          Left () -> embed $ A.wait res           Right (Forklift mvar req) -> do             resp <- liftSem req-            sendM $ putMVar mvar $ pure resp+            embed $ putMVar mvar $ pure resp             me_b       {-# INLINE me #-} 
− src/Polysemy/Internal/Lift.hs
@@ -1,32 +0,0 @@-{-# LANGUAGE NoPolyKinds #-}--{-# OPTIONS_HADDOCK not-home #-}--module Polysemy.Internal.Lift where--import Data.Kind------------------------------------------------------------------------------------ | An effect which allows a regular 'Monad' @m@ into the 'Polysemy.Sem'--- ecosystem. Monadic actions in @m@ can be lifted into 'Polysemy.Sem' via--- 'Polysemy.sendM'.------ For example, you can use this effect to lift 'IO' actions directly into--- 'Polysemy.Sem':------ @--- 'Polysemy.sendM' (putStrLn "hello") :: 'Polysemy.Member' ('Polysemy.Lift' IO) r => 'Polysemy.Sem' r ()--- @------ That being said, you lose out on a significant amount of the benefits of--- 'Polysemy.Sem' by using 'Polysemy.sendM' directly in application code; doing--- so will tie your application code directly to the underlying monad, and--- prevent you from interpreting it differently. For best results, only use--- 'Lift' in your effect interpreters.------ Consider using 'Polysemy.Trace.trace' and 'Polysemy.Trace.runTraceIO' as--- a substitute for using 'putStrLn' directly.-newtype Lift m (z :: Type -> Type) a where-  Lift :: { unLift :: m a } -> Lift m z a-
src/Polysemy/Internal/NonDet.hs view
@@ -6,12 +6,10 @@  module Polysemy.Internal.NonDet where -import Data.Kind - ------------------------------------------------------------------------------ -- | An effect corresponding to the 'Control.Applicative.Alternative' typeclass.-data NonDet (m :: Type -> Type) a+data NonDet m a   = Empty-  | Choose (Bool -> a)+  | Choose (m a) (m a) 
src/Polysemy/Internal/TH/Common.hs view
@@ -1,12 +1,11 @@ {-# LANGUAGE CPP             #-}-{-# LANGUAGE NamedFieldPuns  #-}+{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TupleSections   #-}+{-# LANGUAGE ViewPatterns    #-}  {-# OPTIONS_HADDOCK not-home #-} - module Polysemy.Internal.TH.Common   ( ConLiftInfo (..)   , getEffectMetadata@@ -17,13 +16,15 @@   , makeEffectType   , makeUnambiguousSend   , checkExtensions-  , foldArrows+  , foldArrowTs+  , splitArrowTs+  , pattern (:->)   ) where +import           Control.Arrow ((>>>)) import           Control.Monad import           Data.Bifunctor import           Data.Char (toLower)-import           Data.Either import           Data.Generics hiding (Fixity) import           Data.List import qualified Data.Map.Strict as M@@ -40,30 +41,119 @@   --------------------------------------------------------------------------------- | Given an effect name, eg @''State@, get information about the type--- constructor, and about each of its data constructors.-getEffectMetadata :: Name -> Q (DatatypeInfo, [ConLiftInfo])+-- Effects TH ----------------------------------------------------------------+------------------------------------------------------------------------------++------------------------------------------------------------------------------+-- | Info about constructor being lifted; use 'makeCLInfo' to create one.+data ConLiftInfo = CLInfo+  { -- | Name of effect's type constructor+    cliEffName   :: Name+  , -- | Effect-specific type arguments+    cliEffArgs   :: [Type]+  , -- | Result type specific to action+    cliEffRes    :: Type+  , -- | Name of action constructor+    cliConName   :: Name+  , -- | Name of final function+    cliFunName   :: Name+  , -- | Fixity of function used as an operator+    cliFunFixity :: Maybe Fixity+  , -- | Final function arguments+    cliFunArgs   :: [(Name, Type)]+  , -- | Constraints of final function+    cliFunCxt    :: Cxt+  , -- | Name of type variable parameterizing 'Sem'+    cliUnionName :: Name+  } deriving Show+++------------------------------------------------------------------------------+-- | Given an name of datatype or some of it's constructors/fields, return+-- datatype's name together with info about it's constructors.+getEffectMetadata :: Name -> Q (Name, [ConLiftInfo]) getEffectMetadata type_name = do   dt_info  <- reifyDatatype type_name-  cl_infos <- traverse (mkCLInfo dt_info) $ datatypeCons dt_info-  pure (dt_info, cl_infos)+  cl_infos <- traverse makeCLInfo $ constructorName <$> datatypeCons dt_info+  pure (datatypeName dt_info, cl_infos)   --------------------------------------------------------------------------------- | Turn a 'ConLiftInfo' for @Foo@ into a @Member Foo r@ constraint.-makeMemberConstraint :: Name -> ConLiftInfo -> Pred-makeMemberConstraint r cli = makeMemberConstraint' r $ makeEffectType cli+-- | Creates name of lifting function from action name.+liftFunNameFromCon :: Name -> Name+liftFunNameFromCon n = mkName $+  case nameBase n of+    ':' : cs -> cs+    c   : cs -> toLower c : cs+    ""       -> error "liftFunNameFromCon: empty constructor name"   ------------------------------------------------------------------------------+-- | Creates info about smart constructor being created from name of the+-- original one.+makeCLInfo :: Name -> Q ConLiftInfo+makeCLInfo cliConName = do+  (con_type, cliEffName) <- reify cliConName >>= \case+    DataConI _ t p -> pure (t, p)+    _              -> notDataCon cliConName++  let (con_args, [con_return_type]) = splitAtEnd 1+                                    $ splitArrowTs con_type++  (ty_con_args, [monad_arg, res_arg]) <-+    case splitAtEnd 2 $ tail $ splitAppTs $ con_return_type of+      r@(_, [_, _]) -> pure r+      _             -> missingEffArgs cliEffName++  monad_name   <- maybe (argNotVar cliEffName monad_arg)+                        pure+                        (tVarName monad_arg)++  cliUnionName <- newName "r"++  let normalize_types :: (TypeSubstitution t, Data t) => t -> t+      normalize_types = replaceMArg monad_name cliUnionName+                      . simplifyKinds++      cliEffArgs      = normalize_types ty_con_args+      cliEffRes       = normalize_types res_arg+      cliFunName      = liftFunNameFromCon cliConName++  cliFunFixity  <- reifyFixity cliConName++  fun_arg_names <- replicateM (length con_args) $ newName "x"++  let cliFunArgs    = zip fun_arg_names $ normalize_types con_args+      -- GADTs seem to forbid constraints further in signature, so top level+      -- ones should be fine.+      cliFunCxt     = topLevelConstraints con_type++  pure CLInfo{..}+++------------------------------------------------------------------------------ -- | Given a 'ConLiftInfo', get the corresponding effect type. makeEffectType :: ConLiftInfo -> Type-makeEffectType cli-  = foldl' AppT (ConT $ cliEffName cli)-  $ cliEffArgs cli+makeEffectType cli = foldl' AppT (ConT $ cliEffName cli) $ cliEffArgs cli   ------------------------------------------------------------------------------+-- | @'makeInterpreterType' con r a@ will produce a @'Polysemy.Sem' (Effect ':+-- r) a -> 'Polysemy.Sem' r a@ type, where @Effect@ is the effect+-- corresponding to the 'ConLiftInfo' for @con@.+makeInterpreterType :: ConLiftInfo -> Name -> Type -> Type+makeInterpreterType cli r result = sem_with_eff :-> makeSemType r result where+  sem_with_eff = ConT ''Sem `AppT` r_with_eff `AppT` result+  r_with_eff   = PromotedConsT `AppT` makeEffectType cli `AppT` VarT r+++------------------------------------------------------------------------------+-- | Turn a 'ConLiftInfo' for @Foo@ into a @Member Foo r@ constraint.+makeMemberConstraint :: Name -> ConLiftInfo -> Pred+makeMemberConstraint r cli = makeMemberConstraint' r $ makeEffectType cli+++------------------------------------------------------------------------------ -- | @'makeMemberConstraint'' r type@ will produce a @Member type r@ -- constraint. makeMemberConstraint' :: Name -> Type -> Pred@@ -77,111 +167,39 @@   --------------------------------------------------------------------------------- | @'makeInterpreterType' con r a@ will produce a @'Polysemy.Sem' (Effect ':--- r) a -> 'Polysemy.Sem' r a@ type, where @Effect@ is the effect corresponding--- to the 'ConLiftInfo' for @con@.-makeInterpreterType :: ConLiftInfo -> Name -> Type -> Type-makeInterpreterType cli r result =-  foldArrows (makeSemType r result)-    $ pure-    $ ConT ''Sem-        `AppT` (PromotedConsT `AppT` makeEffectType cli `AppT` VarT r)-        `AppT` result--------------------------------------------------------------------------------- -- | Given a 'ConLiftInfo', this will produce an action for it. It's arguments -- will come from any variables in scope that correspond to the 'cliArgs' of -- the 'ConLiftInfo'. makeUnambiguousSend :: Bool -> ConLiftInfo -> Exp-makeUnambiguousSend should_mk_sigs cli =-  let fun_args_names = fmap fst $ cliArgs cli+makeUnambiguousSend should_make_sigs cli =+  let fun_args_names = fmap fst $ cliFunArgs cli       action = foldl1' AppE              $ ConE (cliConName cli) : (VarE <$> fun_args_names)       eff    = foldl' AppT (ConT $ cliEffName cli) $ args                -- see NOTE(makeSem_)-      args   = (if should_mk_sigs then id else map capturableTVars)-             $ cliEffArgs cli ++ [sem, cliResType cli]+      args   = (if should_make_sigs then id else map capturableTVars)+             $ cliEffArgs cli ++ [sem, cliEffRes cli]       sem    = ConT ''Sem `AppT` VarT (cliUnionName cli)    in AppE (VarE 'send) $ SigE action eff  ---------------------------------------------------------------------------------- | Info about constructor being lifted; use 'mkCLInfo' to create one.-data ConLiftInfo = CLInfo-  { -- | Name of effect's type constructor-    cliEffName   :: Name-    -- | Effect-specific type arguments-  , cliEffArgs   :: [Type]-    -- | Result type specific to action-  , cliResType   :: Type-    -- | Name of action constructor-  , cliConName   :: Name-    -- | Name of final function-  , cliFunName   :: Name-    -- | Fixity of function used as an operator-  , cliFunFixity :: Maybe Fixity-    -- | Final function arguments-  , cliArgs   :: [(Name, Type)]-    -- | Constraints of final function-  , cliFunCxt    :: Cxt-    -- | Name of type variable parameterizing 'Sem'-  , cliUnionName :: Name-  } deriving Show------------------------------------------------------------------------------------ | Creates info about smart constructor being created from info about action--- and it's parent type.-mkCLInfo :: DatatypeInfo -> ConstructorInfo -> Q ConLiftInfo-mkCLInfo dti ci = do-  let cliEffName            = datatypeName dti--  (raw_cli_eff_args, [m_arg, raw_cli_res_arg]) <--    case splitAtEnd 2 $ datatypeInstTypes dti of-      r@(_, [_, _]) -> pure r-      _             -> missingEffArgs cliEffName--  m_name <--    case tVarName m_arg of-      Just r        -> pure r-      Nothing       -> mArgNotVar cliEffName m_arg--  cliUnionName <- newName "r"-  cliFunFixity <- reifyFixity $ constructorName ci--  let normalizeType         = replaceMArg m_name cliUnionName-                            . simplifyKinds-                            . applySubstitution eq_pairs-      -- We extract equality constraints with variables to unify them-      -- manually - this makes type errors more readable. Plus we replace-      -- kind of result with 'Type' if it is a type variable.-      (eq_pairs, cliFunCxt) = first (M.fromList . maybeResKindToType)-                            $ partitionEithers-                            $ eqPairOrCxt <$> constructorContext ci-      maybeResKindToType    = maybe id (\k ps -> (k, StarT) : ps)-                            $ tVarName $ tvKind $ last-                            $ datatypeVars dti--      cliEffArgs            = normalizeType <$> raw_cli_eff_args-      cliResType            = normalizeType     raw_cli_res_arg-      cliConName            = constructorName ci-      cliFunName            = liftFunNameFromCon cliConName-      arg_types             = normalizeType <$> constructorFields ci--  arg_names <- replicateM (length arg_types) $ newName "x"--  pure CLInfo{cliArgs = zip arg_names arg_types, ..}------------------------------------------------------------------------------------ Error messages and checks+-- Error messages and checks ------------------------------------------------- -mArgNotVar :: Name -> Type -> Q a-mArgNotVar name mArg = fail $ show-  $  text "Monad argument ‘" <> ppr mArg <> text "’ in effect ‘"-  <> ppr name <> text "’ is not a type variable"+argNotVar :: Name -> Type -> Q a+argNotVar eff_name arg = fail $ show+  $ text "Argument ‘" <> ppr arg <> text "’ in effect ‘" <> ppr eff_name+    <> text "’ is not a type variable" +-- | Fail the 'Q' monad whenever the given 'Extension's aren't enabled in the+-- current module.+checkExtensions :: [Extension] -> Q ()+checkExtensions exts = do+  states <- zip exts <$> traverse isExtEnabled exts+  maybe (pure ())+        (\(ext, _) -> fail $ show+          $ char '‘' <> text (show ext) <> char '’'+            <+> text "extension needs to be enabled for Polysemy's Template Haskell to work")+        (find (not . snd) states)  missingEffArgs :: Name -> Q a missingEffArgs name = fail $ show@@ -199,32 +217,58 @@     base = capturableBase name     args = PlainTV . mkName <$> ["m", "a"] +notDataCon :: Name -> Q a+notDataCon name = fail $ show+  $ char '‘' <> ppr name <> text "’ is not a data constructor" + --------------------------------------------------------------------------------- | Fail the 'Q' monad whenever the given 'Extension's aren't enabled in the--- current module.-checkExtensions :: [Extension] -> Q ()-checkExtensions exts = do-  states <- zip exts <$> traverse isExtEnabled exts-  maybe (pure ())-        (\(ext, _) -> fail $ show-          $ char '‘' <> text (show ext) <> char '’'-            <+> text "extension needs to be enabled for Polysemy's Template Haskell to work")-        (find (not . snd) states)+-- TH utilities --------------------------------------------------------------+------------------------------------------------------------------------------  ------------------------------------------------------------------------------+-- | Pattern constructing function type and matching on one that may contain+-- type annotations on arrow itself.+infixr 1 :->+pattern (:->) :: Type -> Type -> Type+pattern a :-> b <- (removeTyAnns -> ArrowT) `AppT` a `AppT` b where+  a :-> b = ArrowT `AppT` a `AppT` b+++------------------------------------------------------------------------------ -- | Constructs capturable name from base of input name. capturableBase :: Name -> Name capturableBase = mkName . nameBase + ------------------------------------------------------------------------------+-- | Converts names of all type variables in type to capturable ones based on+-- original name base. Use with caution, may create name conflicts!+capturableTVars :: Type -> Type+capturableTVars = everywhere $ mkT $ \case+  VarT n          -> VarT $ capturableBase n+  ForallT bs cs t -> ForallT (goBndr <$> bs) (capturableTVars <$> cs) t+    where+      goBndr (PlainTV n   ) = PlainTV $ capturableBase n+      goBndr (KindedTV n k) = KindedTV (capturableBase n) $ capturableTVars k+  t -> t+++------------------------------------------------------------------------------+-- | Folds a list of 'Type's into a right-associative arrow 'Type'.+foldArrowTs :: Type -> [Type] -> Type+foldArrowTs = foldr (:->)+++------------------------------------------------------------------------------ -- | Replaces use of @m@ in type with @Sem r@. replaceMArg :: TypeSubstitution t => Name -> Name -> t -> t replaceMArg m r = applySubstitution $ M.singleton m $ ConT ''Sem `AppT` VarT r + ------------------------------------------------------------------------------ -- Removes 'Type' and variable kind signatures from type.-simplifyKinds :: Type -> Type+simplifyKinds :: Data t => t -> t simplifyKinds = everywhere $ mkT $ \case   SigT t StarT    -> t   SigT t VarT{}   -> t@@ -235,54 +279,51 @@       goBndr b = b   t -> t ---------------------------------------------------------------------------------- | Converts equality constraint with type variable to name and type pair if--- possible or leaves constraint as is.-eqPairOrCxt :: Pred -> Either (Name, Type) Pred-eqPairOrCxt p = case asEqualPred p of-  Just (VarT n, b) -> Left (n, b)-  Just (a, VarT n) -> Left (n, a)-  _                -> Right p  --------------------------------------------------------------------------------- | Creates name of lifting function from action name.-liftFunNameFromCon :: Name -> Name-liftFunNameFromCon n = mkName $-  case nameBase n of-    ':' : cs -> cs-    c   : cs -> toLower c : cs-    ""       -> error "liftFunNameFromCon: empty constructor name"+splitAppTs :: Type -> [Type]+splitAppTs = removeTyAnns >>> \case+  t `AppT` arg -> splitAppTs t ++ [arg]+  t            -> [t] + --------------------------------------------------------------------------------- | Folds a list of 'Type's into a right-associative arrow 'Type'.-foldArrows :: Type -> [Type] -> Type-foldArrows = foldr (AppT . AppT ArrowT)+splitArrowTs :: Type -> [Type]+splitArrowTs = removeTyAnns >>> \case+  t :-> ts -> t : splitArrowTs ts+  t        -> [t] + ------------------------------------------------------------------------------ -- | Extracts name from type variable (possibly nested in signature and/or -- some context), returns 'Nothing' otherwise. tVarName :: Type -> Maybe Name-tVarName = \case-  ForallT _ _ t -> tVarName t-  SigT t _      -> tVarName t-  VarT n        -> Just n-  ParensT t     -> tVarName t-  _             -> Nothing+tVarName = removeTyAnns >>> \case+  VarT n -> Just n+  _      -> Nothing + --------------------------------------------------------------------------------- | 'splitAt' counting from the end.-splitAtEnd :: Int -> [a] -> ([a], [a])-splitAtEnd n = swap . join bimap reverse . splitAt n . reverse+topLevelConstraints :: Type -> Cxt+topLevelConstraints = \case+  ForallT _ cs _ -> cs+  _              -> [] + --------------------------------------------------------------------------------- | Converts names of all type variables in type to capturable ones based on--- original name base. Use with caution, may create name conflicts!-capturableTVars :: Type -> Type-capturableTVars = everywhere $ mkT $ \case-  VarT n          -> VarT $ capturableBase n-  ForallT bs cs t -> ForallT (goBndr <$> bs) (capturableTVars <$> cs) t-    where-      goBndr (PlainTV n   ) = PlainTV $ capturableBase n-      goBndr (KindedTV n k) = KindedTV (capturableBase n) $ capturableTVars k+removeTyAnns :: Type -> Type+removeTyAnns = \case+  ForallT _ _ t -> removeTyAnns t+  SigT t _      -> removeTyAnns t+  ParensT t     -> removeTyAnns t   t -> t ++------------------------------------------------------------------------------+-- Miscellaneous -------------------------------------------------------------+------------------------------------------------------------------------------++------------------------------------------------------------------------------+-- | 'splitAt' counting from the end.+splitAtEnd :: Int -> [a] -> ([a], [a])+splitAtEnd n = swap . join bimap reverse . splitAt n . reverse
src/Polysemy/Internal/TH/Effect.hs view
@@ -1,10 +1,7 @@-{-# OPTIONS_HADDOCK not-home #-}--{-# LANGUAGE NamedFieldPuns  #-}-{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TupleSections   #-} +{-# OPTIONS_HADDOCK not-home #-}+ -- | This module provides Template Haskell functions for automatically generating -- effect operation functions (that is, functions that use 'send') from a given -- effect algebra. For example, using the @FileSystem@ effect from the example in@@ -38,6 +35,7 @@ import Polysemy.Internal.CustomErrors (DefiningModule) import Polysemy.Internal.TH.Common + -- TODO: write tests for what should (not) compile  ------------------------------------------------------------------------------@@ -79,7 +77,7 @@ -- * signatures have to specify argument of 'Sem' representing union of -- effects as @r@ (e.g. @'Sem' r ()@) -- * all arguments in effect's type constructor have to follow naming scheme--- from effect's declaration:+-- from data constructor's declaration: -- -- @ -- data Foo e m a where@@ -87,11 +85,11 @@ --   FooC2 :: Foo (Maybe x) m () -- @ ----- should have @e@ in type signature of @fooC1@:+-- should have @x@ in type signature of @fooC1@: ----- @fooC1 :: forall e r. Member (Foo e) r => Sem r ()@+-- @fooC1 :: forall x r. Member (Foo x) r => Sem r ()@ ----- but @x@ in signature of @fooC2@:+-- and @Maybe x@ in signature of @fooC2@: -- -- @fooC2 :: forall x r. Member (Foo (Maybe x)) r => Sem r ()@ --@@ -101,16 +99,19 @@ -- These restrictions may be removed in the future, depending on changes to -- the compiler. --+-- Change in (TODO(Sandy): version): in case of GADTs, signatures now only use+-- names from data constructor's type and not from type constructor+-- declaration.+-- -- @since 0.1.2.0 makeSem_ :: Name -> Q [Dec] makeSem_ = genFreer False -- NOTE(makeSem_):--- This function uses an ugly hack to work --- it enables change of names in--- annotation of applied data constructor to capturable ones, based of names--- in effect's definition. This allows user to provide them to us from their--- signature through 'forall' with 'ScopedTypeVariables' enabled, so that we--- can compile liftings of constructors with ambiguous type arguments (see--- issue #48).+-- This function uses an ugly hack to work --- it changes names in data+-- constructor's type to capturable ones. This allows user to provide them to+-- us from their signature through 'forall' with 'ScopedTypeVariables'+-- enabled, so that we can compile liftings of constructors with ambiguous+-- type arguments (see issue #48). -- -- Please, change this as soon as GHC provides some way of inspecting -- signatures, replacing code or generating haddock documentation in TH.@@ -122,12 +123,12 @@ genFreer :: Bool -> Name -> Q [Dec] genFreer should_mk_sigs type_name = do   checkExtensions [ScopedTypeVariables, FlexibleContexts]-  (dt_info, cl_infos) <- getEffectMetadata type_name+  (dt_name, cl_infos) <- getEffectMetadata type_name   tyfams_on  <- isExtEnabled TypeFamilies   def_mod_fi <- sequence [ tySynInstDCompat                              ''DefiningModule                              Nothing-                             [pure . ConT $ datatypeName dt_info]+                             [pure $ ConT dt_name]                              (LitT . StrTyLit . loc_module <$> location)                          | tyfams_on                          ]@@ -146,13 +147,13 @@   =  maybe [] (pure . flip InfixD (cliFunName cli)) (cliFunFixity cli)   ++ [ SigD (cliFunName cli) $ quantifyType        $ ForallT [] (member_cxt : cliFunCxt cli)-       $ foldArrows sem+       $ foldArrowTs sem        $ fmap snd-       $ cliArgs cli+       $ cliFunArgs cli      ]   where     member_cxt = makeMemberConstraint (cliUnionName cli) cli-    sem        = makeSemType (cliUnionName cli) (cliResType cli)+    sem        = makeSemType (cliUnionName cli) (cliEffRes cli)   ------------------------------------------------------------------------------@@ -160,7 +161,7 @@ -- @x a b c = send (X a b c :: E m a)@. genDec :: Bool -> ConLiftInfo -> Q [Dec] genDec should_mk_sigs cli = do-  let fun_args_names = fmap fst $ cliArgs cli+  let fun_args_names = fmap fst $ cliFunArgs cli    pure     [ PragmaD $ InlineP (cliFunName cli) Inlinable ConLike AllPhases
src/Polysemy/NonDet.hs view
@@ -7,10 +7,15 @@      -- * Interpretations   , runNonDet+  , runNonDetMaybe+  , nonDetToError   ) where  import Control.Applicative+import Control.Monad.Trans.Maybe import Data.Maybe+import Polysemy+import Polysemy.Error import Polysemy.Internal import Polysemy.Internal.NonDet import Polysemy.Internal.Union@@ -55,17 +60,59 @@ ------------------------------------------------------------------------------ -- | Run a 'NonDet' effect in terms of some underlying 'Alternative' @f@. runNonDet :: Alternative f => Sem (NonDet ': r) a -> Sem r (f a)-runNonDet (Sem m) = Sem $ \k -> runNonDetC $ m $ \u ->+runNonDet = runNonDetC . runNonDetInC+{-# INLINE runNonDet #-}++runNonDetInC :: Sem (NonDet ': r) a -> NonDetC (Sem r) a+runNonDetInC = usingSem $ \u ->   case decomp u of     Left x  -> NonDetC $ \cons nil -> do-      z <- k $ weave [()]+      z <- liftSem $ weave [()]                      (fmap concat . traverse runNonDet)                      -- TODO(sandy): Is this the right semantics?                      listToMaybe                      x       foldr cons nil z     Right (Weaving Empty _ _ _ _) -> empty-    Right (Weaving (Choose ek) s _ y _) -> do-      z <- pure (ek False) <|> pure (ek True)-      pure $ y $ z <$ s+    Right (Weaving (Choose left right) s wv ex _) -> fmap ex $+      runNonDetInC (wv (left <$ s)) <|> runNonDetInC (wv (right <$ s))+{-# INLINE runNonDetInC #-} +------------------------------------------------------------------------------+-- | Run a 'NonDet' effect in terms of an underlying 'Maybe'+--+-- Unlike 'runNonDet', uses of '<|>' will not execute the+-- second branch at all if the first option succeeds.+runNonDetMaybe :: Sem (NonDet ': r) a -> Sem r (Maybe a)+runNonDetMaybe (Sem sem) = Sem $ \k -> runMaybeT $ sem $ \u ->+  case decomp u of+    Right (Weaving e s wv ex _) ->+      case e of+        Empty -> empty+        Choose left right ->+          MaybeT $ usingSem k $ runMaybeT $ fmap ex $ do+              MaybeT (runNonDetMaybe (wv (left <$ s)))+          <|> MaybeT (runNonDetMaybe (wv (right <$ s)))+    Left x -> MaybeT $+      k $ weave (Just ())+          (maybe (pure Nothing) runNonDetMaybe)+          id+          x+{-# INLINE runNonDetMaybe #-}++------------------------------------------------------------------------------+-- | Transform a 'NonDet' effect into an @'Error' e@ effect,+-- through providing an exception that 'empty' may be mapped to.+--+-- This allows '<|>' to handle 'throw's of the @'Error' e@ effect.+nonDetToError :: Member (Error e) r+              => e+              -> Sem (NonDet ': r) a+              -> Sem r a+nonDetToError (e :: e) = interpretH $ \case+  Empty -> throw e+  Choose left right -> do+    left'  <- nonDetToError e <$> runT left+    right' <- nonDetToError e <$> runT right+    raise (left' `catch` \(_ :: e) -> right')+{-# INLINE nonDetToError #-}
src/Polysemy/Output.hs view
@@ -8,10 +8,10 @@   , output      -- * Interpretations-  , runOutputAsList-  , runFoldMapOutput-  , runIgnoringOutput-  , runBatchOutput+  , runOutputList+  , runOutputMonoid+  , ignoreOutput+  , runOutputBatched   ) where  import Data.Bifunctor (first)@@ -31,37 +31,43 @@  ------------------------------------------------------------------------------ -- | Run an 'Output' effect by transforming it into a list of its values.-runOutputAsList+--+-- @since 1.0.0.0+runOutputList     :: forall o r a      . Sem (Output o ': r) a     -> Sem r ([o], a)-runOutputAsList = fmap (first reverse) . runState [] . reinterpret+runOutputList = fmap (first reverse) . runState [] . reinterpret   (\case       Output o -> modify (o :)   )-{-# INLINE runOutputAsList #-}+{-# INLINE runOutputList #-}  ------------------------------------------------------------------------------ -- | Run an 'Output' effect by transforming it into a monoid.-runFoldMapOutput+--+-- @since 1.0.0.0+runOutputMonoid     :: forall o m r a      . Monoid m     => (o -> m)     -> Sem (Output o ': r) a     -> Sem r (m, a)-runFoldMapOutput f = runState mempty . reinterpret+runOutputMonoid f = runState mempty . reinterpret   (\case       Output o -> modify (`mappend` f o)   )-{-# INLINE runFoldMapOutput #-}+{-# INLINE runOutputMonoid #-}   ------------------------------------------------------------------------------ -- | Run an 'Output' effect by ignoring it.-runIgnoringOutput :: Sem (Output o ': r) a -> Sem r a-runIgnoringOutput = interpret $ \case+--+-- @since 1.0.0.0+ignoreOutput :: Sem (Output o ': r) a -> Sem r a+ignoreOutput = interpret $ \case   Output _ -> pure ()-{-# INLINE runIgnoringOutput #-}+{-# INLINE ignoreOutput #-}   ------------------------------------------------------------------------------@@ -71,16 +77,17 @@ -- If @size@ is 0, this interpretation will not emit anything in the resulting -- 'Output' effect. ----- @since 0.1.2.0-runBatchOutput+-- @since 1.0.0.0+runOutputBatched     :: forall o r a-     . Int+     . Member (Output [o]) r+    => Int     -> Sem (Output o ': r) a-    -> Sem (Output [o] ': r) a-runBatchOutput 0 m = raise $ runIgnoringOutput m-runBatchOutput size m = do+    -> Sem r a+runOutputBatched 0 m = ignoreOutput m+runOutputBatched size m = do   ((c, res), a) <--    runState (0 :: Int, [] :: [o]) $ reinterpret2 (\case+    runState (0 :: Int, [] :: [o]) $ reinterpret (\case       Output o -> do         (count, acc) <- get         let newCount = 1 + count@@ -91,6 +98,6 @@             output (reverse newAcc)             put (0 :: Int, [] :: [o])     ) m-  when (c > 0) $ output (reverse res)+  when (c > 0) $ output @[o] (reverse res)   pure a 
src/Polysemy/Reader.hs view
@@ -13,7 +13,7 @@   , runReader      -- * Interpretations for Other Effects-  , runInputAsReader+  , inputToReader   ) where  import Polysemy@@ -47,8 +47,10 @@  ------------------------------------------------------------------------------ -- | Transform an 'Input' effect into a 'Reader' effect.-runInputAsReader :: Member (Reader i) r => Sem (Input i ': r) a -> Sem r a-runInputAsReader = interpret $ \case+--+-- @since 1.0.0.0+inputToReader :: Member (Reader i) r => Sem (Input i ': r) a -> Sem r a+inputToReader = interpret $ \case   Input -> ask-{-# INLINE runInputAsReader #-}+{-# INLINE inputToReader #-} 
src/Polysemy/Resource.hs view
@@ -12,8 +12,8 @@      -- * Interpretations   , runResource-  , runResourceInIO-  , runResourceBase+  , lowerResource+  , resourceToIO   ) where  import qualified Control.Exception as X@@ -76,27 +76,25 @@ ------------------------------------------------------------------------------ -- | Run a 'Resource' effect via in terms of 'X.bracket'. ----- __Note:__ This function used to be called @runResource@ prior to 0.4.0.0.------ @since 0.4.0.0-runResourceInIO+-- @since 1.0.0.0+lowerResource     :: ∀ r a-     . Member (Lift IO) r+     . Member (Embed IO) r     => (∀ x. Sem r x -> IO x)        -- ^ Strategy for lowering a 'Sem' action down to 'IO'. This is likely        -- some combination of 'runM' and other interpreters composed via '.@'.     -> Sem (Resource ': r) a     -> Sem r a-runResourceInIO finish = interpretH $ \case+lowerResource finish = interpretH $ \case   Bracket alloc dealloc use -> do     a <- runT  alloc     d <- bindT dealloc     u <- bindT use      let run_it :: Sem (Resource ': r) x -> IO x-        run_it = finish .@ runResourceInIO+        run_it = finish .@ lowerResource -    sendM $ X.bracket (run_it a) (run_it . d) (run_it . u)+    embed $ X.bracket (run_it a) (run_it . d) (run_it . u)    BracketOnError alloc dealloc use -> do     a <- runT  alloc@@ -104,16 +102,16 @@     u <- bindT use      let run_it :: Sem (Resource ': r) x -> IO x-        run_it = finish .@ runResourceInIO+        run_it = finish .@ lowerResource -    sendM $ X.bracketOnError (run_it a) (run_it . d) (run_it . u)-{-# INLINE runResourceInIO #-}+    embed $ X.bracketOnError (run_it a) (run_it . d) (run_it . u)+{-# INLINE lowerResource #-}   ------------------------------------------------------------------------------ -- | Run a 'Resource' effect purely. ----- @since 0.4.0.0+-- @since 1.0.0.0 runResource     :: ∀ r a      . Sem (Resource ': r) a@@ -150,28 +148,28 @@   --------------------------------------------------------------------------------- | A more flexible --- though less safe ---  version of 'runResourceInIO'.+-- | A more flexible --- though less safe ---  version of 'lowerResource'. -- -- This function is capable of running 'Resource' effects anywhere within an -- effect stack, without relying on an explicit function to lower it into 'IO'. -- Notably, this means that 'Polysemy.State.State' effects will be consistent -- in the presence of 'Resource'. ----- 'runResourceBase' is safe whenever you're concerned about exceptions thrown+-- ResourceToIO' is safe whenever you're concerned about exceptions thrown -- by effects _already handled_ in your effect stack, or in 'IO' code run -- directly inside of 'bracket'. It is not safe against exceptions thrown -- explicitly at the main thread. If this is not safe enough for your use-case,--- use 'runResourceInIO' instead.+-- use 'lowerResource' instead. -- -- This function creates a thread, and so should be compiled with @-threaded@. ----- @since 0.5.0.0-runResourceBase+-- @since 1.0.0.0+resourceToIO     :: forall r a-     . LastMember (Lift IO) r+     . LastMember (Embed IO) r     => Sem (Resource ': r) a     -> Sem r a-runResourceBase = interpretH $ \case+resourceToIO = interpretH $ \case   Bracket a b c -> do     ma <- runT a     mb <- bindT b@@ -179,7 +177,7 @@      withLowerToIO $ \lower finish -> do       let done :: Sem (Resource ': r) x -> IO x-          done = lower . raise . runResourceBase+          done = lower . raise . resourceToIO       X.bracket           (done ma)           (\x -> done (mb x) >> finish)@@ -192,9 +190,10 @@      withLowerToIO $ \lower finish -> do       let done :: Sem (Resource ': r) x -> IO x-          done = lower . raise . runResourceBase+          done = lower . raise . resourceToIO       X.bracketOnError           (done ma)           (\x -> done (mb x) >> finish)           (done . mc)-{-# INLINE runResourceBase #-}+{-# INLINE resourceToIO #-}+
src/Polysemy/State.hs view
@@ -12,8 +12,10 @@      -- * Interpretations   , runState+  , evalState   , runLazyState-  , runStateInIORef+  , evalLazyState+  , runStateIORef      -- * Interoperation with MTL   , hoistStateIntoStateT@@ -65,6 +67,15 @@   ------------------------------------------------------------------------------+-- | Run a 'State' effect with local state.+--+-- @since 1.0.0.0+evalState :: s -> Sem (State s ': r) a -> Sem r a+evalState s = fmap snd . runState s+{-# INLINE evalState #-}+++------------------------------------------------------------------------------ -- | Run a 'State' effect with local state, lazily. runLazyState :: s -> Sem (State s ': r) a -> Sem r (s, a) runLazyState = lazilyStateful $ \case@@ -72,21 +83,29 @@   Put s -> const $ pure (s, ()) {-# INLINE[3] runLazyState #-} +------------------------------------------------------------------------------+-- | Run a 'State' effect with local state, lazily.+--+-- @since 1.0.0.0+evalLazyState :: s -> Sem (State s ': r) a -> Sem r a+evalLazyState s = fmap snd . runLazyState s+{-# INLINE evalLazyState #-} + ------------------------------------------------------------------------------ -- | Run a 'State' effect by transforming it into operations over an 'IORef'. ----- @since 0.1.2.0-runStateInIORef+-- @since 1.0.0.0+runStateIORef     :: forall s r a-     . Member (Lift IO) r+     . Member (Embed IO) r     => IORef s     -> Sem (State s ': r) a     -> Sem r a-runStateInIORef ref = interpret $ \case-  Get   -> sendM $ readIORef ref-  Put s -> sendM $ writeIORef ref s-{-# INLINE runStateInIORef #-}+runStateIORef ref = interpret $ \case+  Get   -> embed $ readIORef ref+  Put s -> embed $ writeIORef ref s+{-# INLINE runStateIORef #-}   ------------------------------------------------------------------------------
src/Polysemy/Trace.hs view
@@ -8,13 +8,13 @@   , trace      -- * Interpretations-  , runTraceIO-  , runTraceAsList-  , runIgnoringTrace-  , runTraceAsOutput+  , traceToIO+  , runTraceList+  , ignoreTrace+  , traceToOutput      -- * Interpretations for Other Effects-  , runOutputAsTrace+  , outputToTrace   ) where  import Polysemy@@ -31,56 +31,62 @@  ------------------------------------------------------------------------------ -- | Run a 'Trace' effect by printing the messages to stdout.-runTraceIO :: Member (Lift IO) r => Sem (Trace ': r) a -> Sem r a-runTraceIO = interpret $ \case-  Trace m -> sendM $ putStrLn m-{-# INLINE runTraceIO #-}+--+-- @since 1.0.0.0+traceToIO :: Member (Embed IO) r => Sem (Trace ': r) a -> Sem r a+traceToIO = interpret $ \case+  Trace m -> embed $ putStrLn m+{-# INLINE traceToIO #-}   ------------------------------------------------------------------------------ -- | Run a 'Trace' effect by ignoring all of its messages.-runIgnoringTrace :: Member (Lift IO) r => Sem (Trace ': r) a -> Sem r a-runIgnoringTrace = interpret $ \case+--+-- @since 1.0.0.0+ignoreTrace :: Sem (Trace ': r) a -> Sem r a+ignoreTrace = interpret $ \case   Trace _ -> pure ()-{-# INLINE runIgnoringTrace #-}+{-# INLINE ignoreTrace #-}   ------------------------------------------------------------------------------ -- | Transform a 'Trace' effect into a 'Output' 'String' effect.-runTraceAsOutput+--+-- @since 1.0.0.0+traceToOutput     :: Member (Output String) r     => Sem (Trace ': r) a     -> Sem r a-runTraceAsOutput = interpret $ \case+traceToOutput = interpret $ \case   Trace m -> output m-{-# INLINE runTraceAsOutput #-}+{-# INLINE traceToOutput #-}   ------------------------------------------------------------------------------ -- | Get the result of a 'Trace' effect as a list of 'String's. ----- @since 0.5.0.0-runTraceAsList+-- @since 1.0.0.0+runTraceList     :: Sem (Trace ': r) a     -> Sem r ([String], a)-runTraceAsList = runOutputAsList . reinterpret (+runTraceList = runOutputList . reinterpret (   \case     Trace m -> output m   )-{-# INLINE runTraceAsList #-}+{-# INLINE runTraceList #-}   ------------------------------------------------------------------------------ -- | Transform a 'Trace' effect into a 'Output' 'String' effect. ----- @since 0.1.2.0-runOutputAsTrace+-- @since 1.0.0.0+outputToTrace     :: ( Show w        , Member Trace r        )     => Sem (Output w ': r) a     -> Sem r a-runOutputAsTrace = interpret $ \case+outputToTrace = interpret $ \case   Output m -> trace $ show m-{-# INLINE runOutputAsTrace #-}+{-# INLINE outputToTrace #-} 
src/Polysemy/Writer.hs view
@@ -15,7 +15,7 @@   , runWriter      -- * Interpretations for Other Effects-  , runOutputAsWriter+  , outputToWriter   ) where  import Polysemy@@ -43,10 +43,12 @@  ------------------------------------------------------------------------------ -- | Transform an 'Output' effect into a 'Writer' effect.-runOutputAsWriter :: Member (Writer o) r => Sem (Output o ': r) a -> Sem r a-runOutputAsWriter = interpret $ \case+--+-- @since 1.0.0.0+outputToWriter :: Member (Writer o) r => Sem (Output o ': r) a -> Sem r a+outputToWriter = interpret $ \case   Output o -> tell o-{-# INLINE runOutputAsWriter #-}+{-# INLINE outputToWriter #-}   ------------------------------------------------------------------------------@@ -75,3 +77,4 @@         pure (fmap snd t)   ) {-# INLINE runWriter #-}+
test/AlternativeSpec.hs view
@@ -4,17 +4,24 @@ import Polysemy.NonDet import Test.Hspec import Control.Applicative+import Polysemy.Trace  semFail :: Member NonDet r => Maybe Bool -> Sem r Bool semFail mb = do   Just b <- pure mb   pure b - runAlt :: Alternative f => Sem '[NonDet] a -> f a runAlt = run . runNonDet +failtrace :: (Member NonDet r, Member Trace r)+          => Sem r ()+failtrace = pure () <|> trace "trace" +failtrace' :: (Member NonDet r, Member Trace r)+           => Sem r ()+failtrace' = trace "sim" *> empty <|> trace "salabim"+ spec :: Spec spec = parallel $ do   describe "Alternative instance" $ do@@ -32,3 +39,15 @@       runAlt (semFail $ Just True) `shouldBe` Just True       runAlt (semFail $ Just False) `shouldBe` [False] +  describe "runNonDetMaybe" $ do+    it "should skip second branch if the first branch succeeds" $ do+      (run . runNonDetMaybe . runTraceList) failtrace+        `shouldBe` Just ([], ())+      (run . runTraceList . runNonDetMaybe) failtrace+        `shouldBe` ([], Just ())++    it "should respect local/global state semantics" $ do+      (run . runNonDetMaybe . runTraceList) failtrace'+        `shouldBe` Just (["salabim"], ())+      (run . runTraceList . runNonDetMaybe) failtrace'+        `shouldBe` (["sim", "salabim"], Just ())
test/AsyncSpec.hs view
@@ -15,9 +15,9 @@ spec = describe "async" $ do   it "should thread state and not lock" $ do     (ts, (s, r)) <- runM-                  . runTraceAsList+                  . runTraceList                   . runState "hello"-                  . runAsync $ do+                  . asyncToIO $ do       let message :: Member Trace r => Int -> String -> Sem r ()           message n msg = trace $ mconcat             [ show n, "> ", msg ]@@ -27,14 +27,14 @@           message 1 v           put $ reverse v -          sendM $ threadDelay 1e5+          embed $ threadDelay 1e5           get >>= message 1 -          sendM $ threadDelay 1e5+          embed $ threadDelay 1e5           get @String        void $ async $ do-          sendM $ threadDelay 5e4+          embed $ threadDelay 5e4           get >>= message 2           put "pong" 
test/BracketSpec.hs view
@@ -13,18 +13,18 @@   :: Sem '[Error (), Resource, State [Char], Trace] a   -> ([String], ([Char], Either () a)) runTest = run-        . runTraceAsList+        . runTraceList         . runState ""         . runResource         . runError @()  runTest2-  :: Sem '[Error (), Resource, State [Char], Trace, Lift IO] a+  :: Sem '[Error (), Resource, State [Char], Trace, Embed IO] a   -> IO ([String], ([Char], Either () a)) runTest2 = runM-         . runTraceAsList+         . runTraceList          . runState ""-         . runResourceBase+         . resourceToIO          . runError @()  
test/DoctestSpec.hs view
@@ -23,6 +23,8 @@   , "-XTypeOperators"   , "-XUnicodeSyntax" +  , "-package type-errors"+ #if __GLASGOW_HASKELL__ < 806   , "-XMonadFailDesugaring"   , "-XTypeInType"@@ -32,6 +34,7 @@    -- Modules that are explicitly imported for this test must be listed here   , "src/Polysemy.hs"+  , "src/Polysemy/Error.hs"   , "src/Polysemy/Output.hs"   , "src/Polysemy/Reader.hs"   , "src/Polysemy/Resource.hs"
test/InspectorSpec.hs view
@@ -25,7 +25,7 @@       void . (runM .@ runCallback ref)            . runState False            $ do-        sendM $ pretendPrint ref "hello world"+        embed $ pretendPrint ref "hello world"         callback $ show <$> get @Bool         modify not         callback $ show <$> get @Bool@@ -47,7 +47,7 @@   runCallback-    :: Member (Lift IO) r+    :: Member (Embed IO) r     => IORef [String]     -> (forall x. Sem r x -> IO x)     -> Sem (Callback ': r) a@@ -56,7 +56,7 @@   Callback cb -> do     cb' <- runT cb     ins <- getInspectorT-    sendM $ doCB ref $ do+    embed $ doCB ref $ do       v <- lower .@ runCallback ref $ cb'       pure $ maybe ":(" id $ inspect ins v     getInitialStateT
test/InterceptSpec.hs view
@@ -16,7 +16,7 @@ spec = describe "intercept" $ do   it "should weave through embedded computations" $ do     let (msgs, ()) = run-                   . runTraceAsList+                   . runTraceList                    . runResource                    . withTraceLogging $ do           trace "outside"
test/OutputSpec.hs view
@@ -8,7 +8,7 @@  spec :: Spec spec = parallel $ do-  describe "runBatchOutput" $ do+  describe "runOutputBatched" $ do     it "should return nothing at batch size 0" $ do       let (ms, _) = runOutput 0 $ traverse (output @Int) [0..99]       length ms `shouldBe` 0@@ -23,14 +23,14 @@         it "returns all original elements in the correct order" $           concat ms `shouldBe` [0..99] -  describe "runOutputAsList" $+  describe "runOutputList" $     it "should return elements in the order they were output" $-      let (xs, ()) = runOutputAsList' $ traverse_ (output @Int) [0..100]+      let (xs, ()) = runOutputList' $ traverse_ (output @Int) [0..100]        in xs `shouldBe` [0..100]  -runOutput :: Int -> Sem '[Output Int] a -> ([[Int]], a)-runOutput size = run . runFoldMapOutput (:[]) . runBatchOutput size+runOutput :: Int -> Sem '[Output Int, Output [Int]] a -> ([[Int]], a)+runOutput size = run . runOutputMonoid (:[]) . runOutputBatched size -runOutputAsList' :: Sem '[Output Int] a -> ([Int], a)-runOutputAsList' = run . runOutputAsList+runOutputList' :: Sem '[Output Int] a -> ([Int], a)+runOutputList' = run . runOutputList
test/ThEffectSpec.hs view
@@ -36,12 +36,12 @@  makeSem ''GADTSyntax -data ADTSyntax1 m a = (a ~ Int) => ADTSyntax1C String+data ADTSyntax1 m a = a ~ Int => ADTSyntax1C String  makeSem ''ADTSyntax1  data ADTSyntax2 m a-  = a ~ Int => ADTSyntax2C1 Int+  = a ~ Int    => ADTSyntax2C1 Int   | a ~ String => ADTSyntax2C2 String  makeSem ''ADTSyntax2@@ -69,7 +69,7 @@  -- Data families ------------------------------------------------------------- -data Instance = ADTI | GADTI | NTI+data Instance = ADTI | GADTI | NTI | MMI  data family Family (s :: Instance) (m :: Type -> Type) a @@ -86,6 +86,12 @@ newtype instance Family 'NTI m a = NTIC Int  makeSem 'NTIC++data instance Family 'MMI m (f m) where+  MMIC1 :: f m -> Family 'MMI m (f m)+  MMIC2 :: (forall x. m x -> m (f m)) -> Family 'MMI m (f m)++makeSem 'MMIC1  -- Phantom types ------------------------------------------------------------- 
test/TypeErrors.hs view
@@ -61,13 +61,13 @@ -------------------------------------------------------------------------------- -- | -- >>> :{--- runFoldMapOutput+-- runOutputMonoid --     :: forall o m r a --      . Monoid m --     => (o -> m) --     -> Sem (Output o ': r) a --     -> Sem r (m, a)--- runFoldMapOutput f = runState mempty . reinterpret $ \case+-- runOutputMonoid f = runState mempty . reinterpret $ \case --   Output o -> modify (`mappend` f o) -- :} -- ...@@ -85,13 +85,13 @@ --     foo = pure () --     foo' = reinterpretScrub foo --     foo'' = runState True foo'---     foo''' = runTraceIO foo''+--     foo''' = traceToIO foo'' --  in runM foo''' -- :} -- ...--- ... Unhandled effect 'Lift IO'+-- ... Unhandled effect 'Embed IO' -- ...--- ... Expected type: Sem '[Lift m] (Bool, ())+-- ... Expected type: Sem '[Embed m] (Bool, ()) -- ... Actual type: Sem '[] (Bool, ()) -- ... runningTooManyEffects = ()@@ -116,7 +116,7 @@ -- >>> :{ -- let foo :: Member Resource r => Sem r () --     foo = undefined---  in runM $ runResourceInIO foo+--  in runM $ lowerResource foo -- :} -- ... -- ... Couldn't match expected type ...@@ -142,7 +142,7 @@ -------------------------------------------------------------------------------- -- | -- >>> :{--- foo :: Sem '[State Int, Lift IO] ()+-- foo :: Sem '[State Int, Embed IO] () -- foo = output () -- :} -- ...