HORIZON HASKELLDocslts/ghc-9.14.x45dd5372026-10-11Search names, modules, packages, or :: a typeCtrl K

GHC 9.14.1 · lts/ghc-9.14.x · 45dd537 · 2026-10-11

Moduleeffectful-core-2.7.1.2GHC2021

Effectful.Provider

Turn an effect handler into an effectful operation.

  • 2 types
  • 6 values

Example

0 declarations
Example4 expressions
import Control.Monad.IO.Classimport Data.Map.Strict qualified as Mimport Effectful.Dispatch.Dynamicimport Effectful.State.Static.Local

Given an effect:

Example1 expression
:{  data Write :: Effect where    Write :: String -> Write m ()  type instance DispatchOf Write = Dynamic:}
Example1 expression
:{  write :: Write :> es => String -> Eff es ()  write = send . Write:}

its handler can be turned into an effectful operation with the Provider effect:

Example1 expression
:{  action :: Provider_ Write FilePath :> es => Eff es ()  action = do    provideWith_ @Write "in.txt" $ do      write "hi"      write "there"    provideWith_ @Write "out.txt" $ do      write "good"      write "bye":}

Then, given multiple interpreters:

Example1 expression
:{  runWriteIO    :: IOE :> es    => FilePath    -> Eff (Write : es) a    -> Eff es a  runWriteIO fp = interpret_ $ \case    Write msg -> liftIO . putStrLn $ fp ++ ": " ++ msg:}
Example1 expression
:{  runWritePure    :: State (M.Map FilePath [String]) :> es    => FilePath    -> Eff (Write : es) a    -> Eff es a  runWritePure fp = interpret_ $ \case    Write msg -> modify $ M.insertWith (++) fp [msg]:}

action can be supplied with either of them for the appropriate behavior:

Example1 expression
:{  runEff    . runProvider_ runWriteIO    $ action:}in.txt: hiin.txt: thereout.txt: goodout.txt: bye
Example1 expression
:{  runPureEff    . fmap (fmap reverse)    . execState @(M.Map FilePath [String]) M.empty    . runProvider_ runWritePure    $ action:}fromList [("in.txt",["hi","there"]),("out.txt",["good","bye"])]

Moreover, operations of the Provider effect can be intercepted with interpose, e.g. to adjust the input of the effect handler:

Example1 expression
:{  adjustPaths    :: Provider_ Write FilePath :> es    => Eff es a    -> Eff es a  adjustPaths = interpose @(Provider_ Write FilePath) $ \env -> \case    ProvideWith fp action -> do      passthrough env $ ProvideWith ("logs/" ++ fp) action:}
Example1 expression
:{  runEff    . runProvider_ runWriteIO    . adjustPaths    $ action:}logs/in.txt: hilogs/in.txt: therelogs/out.txt: goodlogs/out.txt: bye

Effect

2 declarations
datadata Provider (e :: Effect) input (f :: Type -> Type) (a :: Type -> Type) b where
#

Provide a way to run a handler of e with a given input.

Note: f can be used to alter the return type of the effect handler. If that's unnecessary, use Provider_.

Constructors

Instances1DispatchOf

Handlers

Operations

valueprovideWith_
  1. :: (HasCallStack, Provider_ e input :> es)
  2. => input

    The input to the effect handler.

  3. -> Eff (e ': es) a
  4. -> Eff es a
#

Run the effect handler that doesn't change its return type with a given input.