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
}