Standard library
Every built-in type, function, and capability available in any Capa program, no imports required. For language syntax and semantics, see the language reference.
Primitive types
| Type | Size/Range | Notes |
|---|---|---|
Int | 64-bit signed | Arithmetic does not check for overflow |
Float | 64-bit IEEE 754 | |
String | UTF-8 | Immutable |
Bool | true / false | |
Char | Unicode code point | At runtime, a str of length 1 |
Unit | () | "Empty" type for functions with no return value |
String, methods
| Method | Type | Description |
|---|---|---|
length() | Int | Number of characters |
is_empty() | Bool | True if the string is empty |
to_upper() | String | Convert to upper case |
to_lower() | String | Convert to lower case |
trim() | String | Strip leading/trailing whitespace |
contains(sub: String) | Bool | Substring is present |
starts_with(s: String) | Bool | |
ends_with(s: String) | Bool | |
split(sep: String) | List<String> | Split by separator |
replace(old: String, new: String) | String | Replace every occurrence |
List<T>
Mutable homogeneous list. Construct with the literal [a, b, c] or by push on a let/var. Cross-statement inference: let xs = [] infers the type from the first push.
| Method | Type | Description |
|---|---|---|
length() | Int | Number of elements |
is_empty() | Bool | |
push(x: T) | () | Append at the end (mutation) |
contains(x: T) | Bool | |
first() | Option<T> | First element or None |
last() | Option<T> | Last element or None |
get(i: Int) | Option<T> | Safe indexed access |
map<U>(f: Fun(T) -> U) | List<U> | Transform each element |
filter(p: Fun(T) -> Bool) | List<T> | Keep elements that match |
fold<U>(init: U, f: Fun(U, T) -> U) | U | Reduce to a single value |
Index access: xs[i] (no bounds checking; use get(i) for safe access).
Range expressions
a..b (exclusive of b) and a..=b (inclusive) produce a List<Int> materialised from the half-open / closed integer range. Both endpoints must be Int. Float endpoints are deliberately excluded.
for i in 0..10 // 0, 1, 2, ..., 9
stdio.println("${i}")
for i in 1..=5 // 1, 2, 3, 4, 5
stdio.println("${i}")
let n = 4
let xs = (n - 1)..(n * 2) // 3..8, arithmetic endpoints
let evens = (0..10).filter(fun (x: Int) -> Bool => x % 2 == 0)
// ranges support the full List API
Range precedence sits between addition and comparison, so 1+2..5+3 parses as (1+2)..(5+3) and a..b == c..d as (a..b) == (c..d). Range itself is non-associative; a..b..c is a syntax error.
Map<K, V>
Hash map. Construct via new_map() with a required type annotation.
| Method | Type | Description |
|---|---|---|
length() | Int | |
is_empty() | Bool | |
get(k: K) | Option<V> | Returns the value if the key exists |
set(k: K, v: V) | () | Insert/update (mutation) |
contains_key(k: K) | Bool | |
keys() | List<K> | |
values() | List<V> |
let m: Map<String, Int> = new_map()
m.set("a", 1)
match m.get("a")
Some(n) -> stdio.println("a = ${n}")
None -> stdio.println("not found")
Set<T>
Set of unique elements. Construct via new_set() with a type annotation.
| Method | Type | Description |
|---|---|---|
length() | Int | |
is_empty() | Bool | |
add(x: T) | () | Add (no-op if duplicate) |
remove(x: T) | () | Remove (no-op if absent) |
contains(x: T) | Bool | |
to_list() | List<T> | Convert to a list |
Option<T>
Built-in sum type:
type Option<T> =
Some(T)
None
| Method | Type | Description |
|---|---|---|
is_some() | Bool | |
is_none() | Bool | |
unwrap_or(default: T) | T | Return value or default |
map<U>(f: Fun(T) -> U) | Option<U> | Transform if Some |
and_then<U>(f: Fun(T) -> Option<U>) | Option<U> | Monadic bind |
ok_or<E>(err: E) | Result<T, E> | Convert to a Result |
Result<T, E>
Built-in sum type for error handling:
type Result<T, E> =
Ok(T)
Err(E)
| Method | Type | Description |
|---|---|---|
is_ok() | Bool | |
is_err() | Bool | |
unwrap_or(default: T) | T | Return value or default |
map<U>(f: Fun(T) -> U) | Result<U, E> | Transform the success value |
and_then<U>(f: Fun(T) -> Result<U, E>) | Result<U, E> | Monadic bind |
map_err<F>(f: Fun(E) -> F) | Result<T, F> | Transform only the error |
The ? operator automatically propagates Err in functions that return Result:
fun read_and_process(fs: Fs) -> Result<Int, IoError>
let content = fs.read("x.txt")? // if Err, returns immediately
return Ok(content.length())
JsonValue
Built-in sum type for JSON representation:
type JsonValue =
JNull
JBool(Bool)
JNum(Float)
JStr(String)
JArr(List<JsonValue>)
JObj(Map<String, JsonValue>)
Extraction methods
| Method | Type | Description |
|---|---|---|
is_null() | Bool | |
as_bool() | Option<Bool> | Some(b) if JBool(b) |
as_num() | Option<Float> | Some(n) if JNum(n) |
as_string() | Option<String> | Some(s) if JStr(s) |
as_array() | Option<List<JsonValue>> | Some(xs) if JArr(xs) |
as_object() | Option<Map<String, JsonValue>> | Some(m) if JObj(m) |
Top-level functions
| Function | Type |
|---|---|
parse_json(s: String) | Result<JsonValue, String> |
to_json(j: JsonValue) | String |
Built-in conversion functions
| Function | Type | Notes |
|---|---|---|
parse_int(s: String) | Option<Int> | Returns None on invalid input |
parse_float(s: String) | Option<Float> | Same for floats |
to_float(i: Int) | Float | Total: every Int has an exact Float representation |
to_int(f: Float) | Int | Truncates toward zero |
new_map() | Map<?, ?> | Requires let annotation to pin the types |
new_set() | Set<?> | Same |
Capa has no implicit numeric coercion: Float + Int is a type error. Use to_float / to_int at the call site to make the conversion explicit:
fun avg(sum: Float, count: Int) -> Float
return sum / to_float(count)
Python interoperability
The two functions below cross the Capa/Python trust boundary. Both require the Unsafe capability as the first argument.
| Function | Type |
|---|---|
py_import(unsafe: Unsafe, name: String) | dynamic (untyped) |
py_invoke(unsafe: Unsafe, callable: ?, args: List<?>) | dynamic (untyped) |
fun square_root(unsafe: Unsafe, x: Float) -> Float
let math = py_import(unsafe, "math")
return py_invoke(unsafe, math.sqrt, [x])
Crossing this boundary loses Capa's static guarantees: the Python value can do anything its type allows, with full ambient authority. The --manifest output marks functions with an Unsafe parameter via has_unsafe: true, so audit tooling can flag them for separate review.
Capabilities
Stdio
| Method | Type | Description |
|---|---|---|
print(s: String) | () | No newline |
println(s: String) | () | With newline |
eprintln(s: String) | () | To stderr |
read_line() | Result<String, IoError> | Read a line without \n |
Fs
| Method | Type | Description |
|---|---|---|
read(p: String) | Result<String, IoError> | Read the entire file |
write(p: String, c: String) | Result<(), IoError> | Write (overwrites) |
exists(p: String) | Bool | Check whether the path exists (returns false on denied paths) |
restrict_to(prefix: String) | Fs | Attenuated Fs allowing only paths under the prefix. Monotonic. |
allows(path: String) | Bool | Query the current restriction set without performing I/O |
Env
| Method | Type | Description |
|---|---|---|
get(name: String) | Option<String> | Environment variable; None for unset or denied keys |
args() | List<String> | Command-line arguments |
restrict_to_keys(keys: List<String>) | Env | Attenuated Env allowing only the listed keys. Monotonic intersection. |
allows(name: String) | Bool | Query the current allowed-key set |
Clock
| Method | Type | Description |
|---|---|---|
now_secs() | Float | Unix time in seconds |
now_monotonic() | Float | Monotonic time |
sleep(seconds: Float) | () | Pause execution (silent no-op on a denied Clock) |
restrict_to_after(t: Float) | Clock | Attenuated Clock active only after timestamp t. Chained calls take the maximum threshold. |
allows() | Bool | Whether the current time has passed the threshold |
Random
| Method | Type | Description |
|---|---|---|
int_range(low: Int, high: Int) | Int | Integer in [low, high) |
float_unit() | Float | Float in [0, 1) |
with_seed(seed: Int) | Random | Deterministic sequence from the given seed. Re-seeding overwrites. |
Net
| Method | Type | Description |
|---|---|---|
restrict_to(host: String) | Net | Attenuate: return a fresh Net whose authority is the intersection of the current allowed-host set with {host}. Monotonic; restrictions only narrow. |
allows(host: String) | Bool | Query the current restriction set; performs no I/O. |
get(url: String) | Result<String, IoError> | Real HTTP GET (via urllib.request). Returns Err immediately if the URL's host is outside the current restriction set, before any system call. |
A Net received from main is unrestricted; restrictions accumulate through restrict_to. The result of restrict_to is a fresh capability instance and is bindable in a let/var; Capa relaxes the "no capabilities in locals" rule specifically for method-call results (which are necessarily fresh, not aliases of an existing capability).
fun fetch(net: Net) -> Result<String, IoError>
return net.get("https://api.example.com/users")
fun main(net: Net, stdio: Stdio)
let api = net.restrict_to("api.example.com")
match fetch(api)
Ok(body) -> stdio.println(body)
Err(e) -> stdio.eprintln("${e}")
See examples/net_attenuation.capa for a fuller demonstration, including the monotonic-narrowing property (chaining two disjoint restrictions yields a Net that allows nothing).
Unsafe
Marker capability for crossing the Python boundary. Has no methods, its only role is to gate py_import and py_invoke (see the Python interoperability section above).
User-defined capabilities
Libraries can declare their own capabilities with the capability keyword. The declaration registers the name in the capability discipline; any type that implements the capability becomes a valid implementor.
capability SendEmail
fun send(self, to: String, subject: String, body: String) -> Result<Unit, IoError>
type SmtpMailer {
server: String,
net: Net // built-in cap as a field, allowed because
// SmtpMailer implements a user-defined cap
}
impl SendEmail for SmtpMailer
fun send(self, to: String, subject: String, body: String) -> Result<Unit, IoError>
// delegate to self.net under the hood
return Ok(())
// Factory that consumes the underlying built-in cap and produces the
// higher-level capability. Allowed return type even though SmtpMailer
// carries authority.
fun make_smtp_mailer(net: Net, server: String) -> SmtpMailer
return SmtpMailer { server: server, net: net.restrict_to(server) }
// Caller side: receive the capability by parameter (subtyping accepts
// SmtpMailer where SendEmail is expected because of the impl).
fun send_welcome(mailer: SendEmail, to: String) -> Result<Unit, IoError>
return mailer.send(to, "Welcome", "Hello!")
The discipline still applies: a let dup = mailer (plain identifier alias of a cap-bearing value) is rejected; only call/method-call right-hand sides produce fresh capability instances that can be bound. See examples/user_capabilities.capa for a complete example.
The IoError type
Opaque type representing I/O errors. Available as a type parameter in Result<T, IoError> and in pattern matching:
match fs.read("x.txt")
Ok(content) -> stdio.println(content)
Err(e) -> stdio.eprintln("error: ${e}")
IoError's string representation is human-readable, but its internal contents are private.