Skip to content
Kavachकवच

Your Own Capabilities: Declaring a capability

● Intermediate3 min

A capability names methods. Every method can be refused, so its error type must have a Denied(reason: String) case.

Called where nothing implements it, a capability is refused: it never fails silently, and never does something unexpected:

type PayError = Declined | Denied(reason: String)

capability Payments {
    fn refund(order: Int, amount: Int) ! PayError
}

fn main() {
    Payments.refund(7, 499) catch e => print("refused: {e}")
}

The program ran and printed:

kavach run own-declare.kav

refused: Denied(reason: "no implementation of Payments")
own-declare.kav: Kavach code, then what running it prints

A limit, a person who says no, or a missing implementation can refuse any call. So the compiler insists on the Denied case, and the refusal is visible to anyone reading the code:

type PayError = Declined | Unavailable

capability Payments {
    fn refund(order: Int, amount: Int) ! PayError
}

The compiler refused the program:

kavach run own-no-denied.kav

error: `Payments.refund` can be refused, so its error type needs a variant `Denied(reason: String)` (spec 8.2)
own-no-denied.kav: Kavach code, then what running it prints