Effect rows

The with { ... } clause is the complete list of what a function does beyond computing its result: which capabilities it uses, and which effects it can raise. The row is a set, sorted and deduplicated. ? propagates one kind of effect, err: T, and nothing else.

function load(rfs: ReadOnlyFilesystem, path: String, allocator: Allocator) -> Config
    with {rfs, allocator, err: fs.FsError, err: str.ParseFloatError}
{
    let text = fs.read_to_string(rfs, path, allocator)?
    return parse_config(text)?
}

The pure effects are err: T, panic, yield: T, cancellation, divergence, and nondet. Graded effects add a static bound, checked at compile time: alloc(bytes <= 4096), io(calls <= 1), time(ops <= N). A handler removes an effect from the row:

handle err: fs.FsError as e -> default_for(e) {
    read_config(rfs, path, allocator)?
}