Skuld.Effects.Reader (skuld v0.33.0)

Copy Markdown View Source

Reader effect - access an immutable environment value.

Supports both simple single-context usage and multiple independent contexts via tags.

Tag Convention

Tags should be module atoms — either the effect module itself (Reader) for singleton context, or a derived atom (MyApp.Config, Reader.DB) for namespaced contexts. Module atoms are globally unique by construction, eliminating accidental collisions between independent pieces of context.

Simple Usage (default tag)

use Skuld.Syntax
alias Skuld.Effects.Reader

comp do
  cfg <- Reader.ask()
  cfg.name
end
|> Reader.with_handler(%{name: "alice"})
|> Comp.run!()
#=> "alice"

Multiple Contexts (explicit tags)

comp do
  db <- Reader.ask(:db)
  api <- Reader.ask(:api)
  {db.host, api.url}
end
|> Reader.with_handler(%{host: "localhost"}, tag: :db)
|> Reader.with_handler(%{url: "https://api.example.com"}, tag: :api)
|> Comp.run!()
#=> {"localhost", "https://api.example.com"}

Per-tag dispatch

Each tag gets its own handler sig (a module atom) and compact operation atom. The tag is encoded in the sig, not in the operation args:

  • askComp.effect(sig(tag), Reader.Ask) — bare atom, zero allocation

Summary

Functions

Install Reader handler via catch clause syntax.

Read and apply a function to the environment value.

Extract the context value for the given tag from an env

Run a computation with a modified environment value.

Install a scoped Reader handler for a computation.

Functions

__handle__(comp, value)

Install Reader handler via catch clause syntax.

Accepts either value or {value, opts}:

catch
  Reader -> %{config: true}
  Reader -> {%{config: true}, tag: :my_reader}

asks(f)

@spec asks((term() -> term())) :: Skuld.Comp.Types.computation()

Read and apply a function to the environment value.

Examples

Reader.asks(&Map.get(&1, :name))           # use default tag
Reader.asks(:user, &Map.get(&1, :name))    # use explicit tag

asks(tag, f)

@spec asks(atom(), (term() -> term())) :: Skuld.Comp.Types.computation()

get_context(env, tag \\ Skuld.Effects.Reader)

@spec get_context(Skuld.Comp.Types.env(), atom()) :: term()

Extract the context value for the given tag from an env

local(modify, comp)

Run a computation with a modified environment value.

Examples

Reader.local(&Map.put(&1, :debug, true), comp)           # use default tag
Reader.local(:config, &Map.put(&1, :debug, true), comp)  # use explicit tag

local(tag, modify, comp)

state_key(tag)

with_handler(comp, value, opts \\ [])

Install a scoped Reader handler for a computation.

Options

Examples

# Simple usage with default tag
comp do
  cfg <- Reader.ask()
  cfg.name
end
|> Reader.with_handler(%{name: "alice"})
|> Comp.run!()
#=> "alice"

# With explicit tag
comp do
  db <- Reader.ask(:db)
  db.host
end
|> Reader.with_handler(%{host: "localhost"}, tag: :db)
|> Comp.run!()
#=> "localhost"

# Multiple contexts
comp do
  db <- Reader.ask(:db)
  cache <- Reader.ask(:cache)
  {db, cache}
end
|> Reader.with_handler(%{host: "db.local"}, tag: :db)
|> Reader.with_handler(%{host: "cache.local"}, tag: :cache)
|> Comp.run!()
#=> {%{host: "db.local"}, %{host: "cache.local"}}