Result

The Result module provides utilities for error handling. Result types represent operations that can succeed with a value or fail with an error, providing a type-safe alternative to exceptions.

Constructors

Results are created using the Ok and Err constructors, which are pre-registered in Kit and available without import.

Constructors

Ok
a -> Result a e
Wraps a value in an Ok, indicating the operation succeeded.
value = Ok 42
name = Ok "Alice"
Err
e -> Result a e
Wraps an error value in an Err, indicating the operation failed.
error = Err "File not found"
invalid = Err { code: 404, message: "Not found" }

Predicates

Result.is-ok?
Result a e -> Bool
Returns true if the result is an Ok value.
println (Result.is-ok? (Ok 42))
# => true

println (Result.is-ok? (Err "error"))
# => false
Result.is-err?
Result a e -> Bool
Returns true if the result is an Err value.
println (Result.is-err? (Err "error"))
# => true

println (Result.is-err? (Ok 42))
# => false
is-ok?
Result a e -> Bool
Bare function that checks if a result is an Ok value.
println (is-ok? (Ok 42))
# => true
is-err?
Result a e -> Bool
Bare function that checks if a result is an Err value.
println (is-err? (Err "error"))
# => true

Transforming

Result.map
(a -> b) -> Result a e -> Result b e
Applies a function to the value inside an Ok, or passes through the Err.
double = fn(x) => x * 2

result = Result.map double (Ok 21)
# => Ok 42

error = Result.map double (Err "failed")
# => Err "failed"
Result.map-err
(e -> f) -> Result a e -> Result a f
Applies a function to the error inside an Err, or passes through the Ok.
add-context = fn(err) => "Database error: ${err}"

result = Result.map-err add-context (Err "connection refused")
# => Err "Database error: connection refused"

Unwrapping

Result.unwrap
Result a e -> a
Returns the value inside an Ok. Raises an error if Err. Prefer Result.unwrap-or or pattern matching when possible.
value = Result.unwrap (Ok 42)
# => 42

# This will raise an error:
# Result.unwrap (Err "failed")
Result.unwrap-or
a -> Result a e -> a
Returns the value inside an Ok, or the provided default if Err.
value = Result.unwrap-or 0 (Ok 42)
# => 42

default = Result.unwrap-or 0 (Err "error")
# => 0

Chaining

Result.and-then
(a -> Result b e) -> Result a e -> Result b e
Chains fallible operations. If the input is Ok, applies the function. If Err, passes through the error.
parse-int = fn(s) =>
    match String.to-int s
        | Some n -> Ok n
        | None -> Err "Invalid integer"

validate-positive = fn(n) =>
    if n > 0 then Ok n else Err "Must be positive"

result = Ok "42"
    |> Result.and-then parse-int
    |> Result.and-then validate-positive
# => Ok 42

Pattern Matching with Results

Results are typically handled using pattern matching:

process = fn(result) =>
    match result
        | Ok value -> "Success: ${value}"
        | Err error -> "Error: ${error}"

println (process (Ok 42))
# => "Success: 42"

println (process (Err "not found"))
# => "Error: not found"

Common Patterns

Combining Multiple Results

read-config = fn(path) =>
    match File.read path
        | Ok content -> Ok content
        | Err err -> Err "Config error: ${err}"

validate-config = fn(content) =>
    if String.length content > 0
        then Ok content
        else Err "Config is empty"

# Chain operations using pipe and and-then
config = read-config "app.toml"
    |> Result.and-then validate-config
    |> Result.map String.trim

Converting Option to Result

ok-or = fn(error, option) =>
    match option
        | Some value -> Ok value
        | None -> Err error

result = Map.get "key" my-map |> ok-or "Key not found"