Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Get and GetMut — Extracting from Context

Get and GetMut are type-level lookup traits for HList contexts.

Get: Read-Only Access

use effectful::{Get, Here};

fn use_database<R>(env: &R) -> &Pool
where
    R: Get<DatabaseKey, Here, Target = Pool>,
{
    env.get()
}

The path parameter tells the compiler where the cell lives. Here means the head of the list.

GetMut: Mutable Access

use effectful::{GetMut, Here};

fn increment_counter<R>(env: &mut R)
where
    R: GetMut<CounterKey, Here, Target = Counter>,
{
    let counter = env.get_mut();
    counter.increment();
}

Use GetMut sparingly. For shared concurrent state, prefer TRef or a service that owns its mutation rules.

Explicit Paths

For values not at the head, use a path such as ThereHere or Skip1.

let logger: &Logger = env.get_path::<LoggerKey, ThereHere>();

Lookup is type-safe, but not magical: the path is part of the bound.

No bind* Tag Shorthand

The current effect! macro only binds expressions whose type implements the bind protocol, usually Effect<_, _, _>.

effect! {
    let user = bind* fetch_user(id);
    user
}

It does not support bind* DatabaseKey service lookup shorthand. Access tagged contexts with Context::get / Get, or use derive-service helpers such as UserRepository::use_.

NeedsX Supertraits

You can hide verbose Get bounds behind a trait.

pub trait NeedsDatabase: Get<DatabaseKey, Here, Target = Pool> {}
impl<R: Get<DatabaseKey, Here, Target = Pool>> NeedsDatabase for R {}

This is only a naming pattern; the compiler still verifies the underlying Get bound.

Compile-Time Guarantees

If a function requires NeedsDatabase, callers must supply an environment type that satisfies that trait. Missing tagged cells are compile-time errors for HList Contexts.