polysemy-resume-0.5.0.0: Polysemy error tracking
Safe HaskellSafe-Inferred
LanguageHaskell2010

Polysemy.Resume.Resumable

Synopsis

Documentation

type InterpreterTrans' eff eff' r r' = forall a b. (Sem (eff' ': r') a -> Sem r b) -> Sem (eff ': r) a -> Sem r b Source #

type InterpreterTrans eff eff' r = InterpreterTrans' eff eff' r r Source #

distribEither :: Functor f => f () -> (f (Either err a) -> res) -> Either err (f a) -> res Source #

resumable :: forall (err :: Type) (eff :: Effect) (r :: EffectRow). InterpreterFor eff (Stop err ': r) -> InterpreterFor (Resumable err eff) r Source #

Convert a bare interpreter for eff, which (potentially) uses Stop to signal errors, into an interpreter for Resumable. Beware: This will display unsound behaviour if: * the interpreter is wrapped with actions of another effect, as in:

  interpretEff :: InterpreterFor Eff r
  ...

  interpretEffResumable :: InterpreterFor (Resumable Text Eff) r
  interpretEffResumable sem =
  resumable (interpretEff (sem finally releaseResources))
  

In this case, releaseResources will be called after every use of Eff in sem, not after the entire thunk.

  • the interpreter of a higher-order effect uses a different interpreter after using runT/bindT. In this case, it will use the original interpreter instead.

If your use case matches one of these conditions, you'll need to use interpretResumable.

>>> run $ resumable interpretStopper (interpretResumer mainProgram)
237

raiseResumable :: forall (err :: Type) (eff :: Effect) (r :: EffectRow). InterpreterTrans (Resumable err eff) eff r Source #

Convenience combinator for turning an interpreter that doesn't use Stop into a Resumable.

resumableIO :: forall (err :: Type) (eff :: Effect) (r :: EffectRow). Exception (StopExc err) => Member (Final IO) r => InterpreterFor eff (Stop err ': r) -> InterpreterFor (Resumable err eff) r Source #

Like resumable, but use exceptions instead of ExceptT.

interpretResumableH Source #

Arguments

:: forall (err :: Type) (eff :: Effect) (r :: EffectRow). (forall x r0. eff (Sem r0) x -> Tactical (Resumable err eff) (Sem r0) (Stop err ': r) x)

This handler function has Stop err in its stack, allowing it to absorb errors.

-> InterpreterFor (Resumable err eff) r 

Like interpretResumable, but for higher-order effects.

interpretResumable :: forall (err :: Type) (eff :: Effect) r. FirstOrder eff "interpretResumable" => (forall x r0. eff (Sem r0) x -> Sem (Stop err ': r) x) -> InterpreterFor (Resumable err eff) r Source #

Create an interpreter for Resumable err eff by supplying a handler function for eff, analogous to interpret. If the handler throws errors with Stop, they will be absorbed into Resumable, to be caught by resume in a downstream interpreter.

interpretStopperResumable ::
  InterpreterFor Stopper r
interpretStopperResumable =
  interpretResumable \case
    StopBang -> stop (Bang 13)
    StopBoom -> stop (Boom "ouch")
>>> run $ interpretStopperResumable (interpretResumer mainProgram)
237

interceptResumableUsingH :: forall (err :: Type) (eff :: Effect) (r :: EffectRow) (a :: Type). ElemOf (Resumable err eff) r -> (forall x r0. eff (Sem r0) x -> Tactical (Resumable err eff) (Sem r0) (Stop err ': r) x) -> Sem r a -> Sem r a Source #

Interceptor variant of interpretResumableH.

interceptResumableUsing :: forall (err :: Type) (eff :: Effect) (r :: EffectRow) (a :: Type). FirstOrder eff "interceptResumableUsing" => ElemOf (Resumable err eff) r -> (forall x r0. eff (Sem r0) x -> Sem (Stop err ': r) x) -> Sem r a -> Sem r a Source #

Interceptor variant of interpretResumable.

interceptResumableH :: forall (err :: Type) (eff :: Effect) (r :: EffectRow) (a :: Type). Member (Resumable err eff) r => (forall x r0. eff (Sem r0) x -> Tactical (Resumable err eff) (Sem r0) (Stop err ': r) x) -> Sem r a -> Sem r a Source #

Interceptor variant of interpretResumableH.

interceptResumable :: forall (err :: Type) (eff :: Effect) (r :: EffectRow) (a :: Type). Member (Resumable err eff) r => FirstOrder eff "interceptResumable" => (forall x r0. eff (Sem r0) x -> Sem (Stop err ': r) x) -> Sem r a -> Sem r a Source #

Interceptor variant of interpretResumable.

resumableError :: forall (err :: Type) (eff :: Effect) r. InterpreterFor eff (Error err ': (Stop err ': r)) -> InterpreterFor (Resumable err eff) r Source #

Convert an interpreter for eff that uses Error into one using Stop and wrap it using resumable.

resumableOr :: forall (err :: Type) (eff :: Effect) unhandled handled r. Member (Error unhandled) r => (err -> Either unhandled handled) -> InterpreterFor eff (Stop err ': r) -> InterpreterFor (Resumable handled eff) r Source #

Convert an interpreter for eff that throws errors of type err into a Resumable, but limiting the errors handled by consumers to the type handled, which rethrowing Errors of type unhandled.

The function canHandle determines how the errors are split.

newtype Blip =
  Blip { unBlip :: Int }
  deriving (Eq, Show)

bangOnly :: Boom -> Either Text Blip
bangOnly = \case
  Bang n -> Right (Blip n)
  Boom msg -> Left msg

interpretResumerPartial ::
  Member (Resumable Blip Stopper) r =>
  InterpreterFor Resumer r
interpretResumerPartial =
  interpret \ MainProgram ->
    resume (192 <$ stopBang) \ (Blip num) ->
      pure (num * 3)
>>> runError (resumableFor bangOnly interpretStopper (interpretResumerPartial mainProgram))
Right 39

resumableFor :: forall (err :: Type) (eff :: Effect) handled r. Member (Error err) r => (err -> Maybe handled) -> InterpreterFor eff (Stop err ': r) -> InterpreterFor (Resumable handled eff) r Source #

Variant of resumableOr that uses Maybe and rethrows the original error.

catchResumable :: forall (err :: Type) (eff :: Effect) handled r. Members [eff, Error err] r => (err -> Maybe handled) -> InterpreterFor (Resumable handled eff) r Source #

Reinterpreting variant of resumableFor.

runAsResumable :: forall (err :: Type) (eff :: Effect) r. Members [Resumable err eff, Stop err] r => InterpreterFor eff r Source #

Interpret an effect eff by wrapping it in Resumable and Stop and leaving the rest up to the user.