Requirements and providing them
require(T) reads a dependency and records it in the R channel; composing effects unions their requirements, exactly like errors. the runners only accept Effect[A, E], so running an effect with unmet requirements is a type error, not a runtime surprise.
@(frozen=True)
class :
:
= E.().(lambda : .) # Effect[str, Never, Db]
program = .()(("postgres://x")) # Effect[str] — runnable
E.() # "postgres://x"provide(T)(impl) subtracts the provided type from R, so requirements can be provided one at a time, anywhere in the program — a partially provided effect is an ordinary value carrying the remainder in R, and the runners accept it only once R reaches Never.
More examples: test_run_sync.py.