module Polysemy.Resume ( -- * Introduction -- $intro module Polysemy.Resume.Data.Stop, module Polysemy.Resume.Data.Resumable, -- * Resuming a Stopped Computation resume, (!!), interpretResumable, interpretResumableH, resumable, raiseResumable, resumableIO, -- * Partial Handlers -- $partial resumableOr, -- * Various Combinators resumeAs, (<!), (!>), resumeWith, (!>>), resumingWith, (<<!), resume_, resumeHoist, resumeHoistAs, resuming, resumeHoistError, resumeHoistErrorAs, restop, resumeEither, resumeOr, resumingOr, resumeError, resumableError, resumableFor, runAsResumable, catchResumable, module Polysemy.Resume.Stop, ) where import Polysemy.Resume.Data.Resumable (Resumable, type (!!)) import Polysemy.Resume.Data.Stop (Stop (..), stop) import Polysemy.Resume.Resumable ( catchResumable, interpretResumable, interpretResumableH, raiseResumable, resumable, resumableError, resumableFor, resumableIO, resumableOr, runAsResumable, ) import Polysemy.Resume.Resume ( restop, resume, resumeAs, resumeEither, resumeError, resumeHoist, resumeHoistAs, resumeHoistError, resumeHoistErrorAs, resumeOr, resumeWith, resume_, resuming, resumingOr, resumingWith, (!!), (!>), (!>>), (<!), (<<!), ) import Polysemy.Resume.Stop ( mapStop, runStop, showStop, stopEither, stopEitherWith, stopNote, stopOnError, stopOnErrorWith, stopToError, stopToIOFinal, ) -- $intro -- This library provides the Polysemy effects 'Resumable' and 'Stop' for the purpose of safely connecting throwing and -- catching errors across different interpreters. -- -- Consider the effect: -- -- @ -- data Stopper :: Effect where -- StopBang :: Stopper m () -- StopBoom :: Stopper m () -- -- makeSem ''Stopper -- -- data Boom = -- Boom { unBoom :: Text } -- | -- Bang { unBang :: Int } -- deriving (Eq, Show) -- -- interpretStopper :: -- Member (Error Boom) r => -- InterpreterFor Stopper r -- interpretStopper = -- interpret \\case -- StopBang -> throw (Bang 13) -- StopBoom -> throw (Boom "ouch") -- @ -- -- If we want to use @Stopper@ in the interpreter of another effect, we have no way of knowing about the errors thrown -- by its interpreter, even though we can catch @Boom@! -- This library makes the connection explicit by changing 'Polysemy.Error.Error' to 'Stop' and wrapping 'Stopper' in -- 'Resumable' when using it in an effect stack: -- $partial -- In some cases, the errors thrown by an interpreter contain details about the implementation, which we might want to -- hide from dependents; or it may throw fatal errors we don't want to handle at all. -- For this purpose, we can create partial 'Resumable's by transforming errors before handling them: