Download

10. Errors

"Errors as values" model#

Errors are ordinary values (Error unions, below).

read_file :: fn(path: string) -> string | IOError {
    // ...
}

Error unions#

A function that can fail returns its success type in a union with one or more error types, written out (parse_int :: fn(s: string) -> i32 | ParseError): there is no shorthand such as a postfix !.

Error trait#

Error :: trait {
    message :: fn(self) -> string
}

The standard library's errors (IOError, ParseError, ...) implement it. In a union such as T | Error, the member Error holds a value of any type implementing it.

Error propagation#

An error propagates by a test and a return; past the test, the value is narrowed to its success type (§3 Type tests and narrowing):

process :: fn(path: string) -> string | Error {
    raw :: read_file(path)
    if raw is Error { return raw }    // raw is `string` below
    return parse(raw)
}

Explicit match#

An error handled in place is matched like any other union:

r :: read_file("a.txt")
match r {
    is string -> println("got: ${r}")
    is Error  -> println("error: ${r.message()}")    // virtual dispatch
}