rectify/result_option

ResultOption utilities for Rectify

Helpers for working with Result(Option(a), e) — a common pattern for operations that can fail AND may not return a value.

We refer to this as “ResultOption” for brevity, but it’s not a distinct type — just the composed Result(Option(a), e) pattern.

Instead of nested pattern matching, use these combinators.

Values

pub fn bind(
  ro: Result(option.Option(a), e),
  f: fn(a) -> Result(option.Option(b), e),
) -> Result(option.Option(b), e)

Bind over ResultOption.

Examples

bind(Ok(Some(5)), fn(n) { Ok(Some(n * 2)) })
// -> Ok(Some(10))
bind(Ok(None), fn(n) { Ok(Some(n * 2)) })
// -> Ok(None)
pub fn error(e: e) -> Result(option.Option(a), e)

Create an error Result.

Examples

error("not found")
// -> Error("not found")
pub fn is_none(ro: Result(option.Option(a), e)) -> Bool

Check if ResultOption contains None.

Examples

is_none(Ok(None))
// -> True
is_none(Ok(Some(42)))
// -> False
is_none(Error("e"))
// -> False
pub fn is_some(ro: Result(option.Option(a), e)) -> Bool

Check if ResultOption contains Some value.

Examples

is_some(Ok(Some(42)))
// -> True
is_some(Ok(None))
// -> False
is_some(Error("e"))
// -> False
pub fn map(
  ro: Result(option.Option(a), e),
  f: fn(a) -> b,
) -> Result(option.Option(b), e)

Map over the value inside ResultOption, if both succeed.

Examples

map(Ok(Some(5)), fn(n) { n * 2 })
// -> Ok(Some(10))
map(Ok(None), fn(n) { n * 2 })
// -> Ok(None)
map(Error("e"), fn(n) { n * 2 })
// -> Error("e")
pub fn none() -> Result(option.Option(a), e)

Create a Result containing None.

Examples

none()
// -> Ok(None)
pub fn of_option(
  opt: option.Option(a),
) -> Result(option.Option(a), e)

Convert Option to ResultOption, wrapping in Ok.

Examples

of_option(Some(42))
// -> Ok(Some(42))
of_option(None)
// -> Ok(None)
pub fn of_result(
  result: Result(a, e),
) -> Result(option.Option(a), e)

Convert Result to ResultOption, wrapping success in Some.

Examples

of_result(Ok(42))
// -> Ok(Some(42))
of_result(Error("e"))
// -> Error("e")
pub fn sequence(
  items: List(Result(option.Option(a), e)),
) -> Result(option.Option(List(a)), e)

Convert a list of ResultOptions into a ResultOption of a list.

  • If any is Error(e), returns Error(e)
  • If all are Ok but any are Ok(None), returns Ok(None)
  • If all are Ok(Some(value)), returns Ok(Some([values]))

This is the special case of traverse where the function is identity.

Examples

sequence([Ok(Some(1)), Ok(Some(2)), Ok(Some(3))])
// -> Ok(Some([1, 2, 3]))
sequence([Ok(Some(1)), Ok(None), Ok(Some(3))])
// -> Ok(None)
sequence([Ok(Some(1)), Error("e"), Ok(Some(3))])
// -> Error("e")
sequence([])
// -> Ok(Some([]))
pub fn some(a: a) -> Result(option.Option(a), e)

Create a Result containing Some value.

Examples

some(42)
// -> Ok(Some(42))
pub fn to_option(
  ro: Result(option.Option(a), e),
) -> option.Option(a)

Convert ResultOption to Option(a), losing error information.

Examples

to_option(Ok(Some(42)))
// -> Some(42)
to_option(Ok(None))
// -> None
to_option(Error("e"))
// -> None
pub fn to_result(
  ro: Result(option.Option(a), e),
  default: a,
) -> Result(a, e)

Convert ResultOption to a plain Result, with a default for None.

Examples

to_result(Ok(Some(42)), 0)
// -> Ok(42)
to_result(Ok(None), 0)
// -> Ok(0)
to_result(Error("e"), 0)
// -> Error("e")
pub fn traverse(
  items: List(a),
  f: fn(a) -> Result(option.Option(b), e),
) -> Result(option.Option(List(b)), e)

Apply a function that returns ResultOption to each element of a list, collecting the results.

  • If any function returns Error(e), returns Error(e) (fail fast)
  • If all are Ok but any are Ok(None), returns Ok(None)
  • If all are Ok(Some(value)), returns Ok(Some([values]))

This is useful for operations like “look up all these IDs in the database, fail if any lookup errors, return None if any not found”.

Examples

// All found
traverse([1, 2, 3], fn(id) { Ok(Some(id * 10)) })
// -> Ok(Some([10, 20, 30]))
// One not found
traverse([1, 2, 3], fn(id) {
  case id == 2 {
    True -> Ok(None)
    False -> Ok(Some(id * 10))
  }
})
// -> Ok(None)
// One errors
traverse([1, 2, 3], fn(id) {
  case id == 2 {
    True -> Error("not found")
    False -> Ok(Some(id * 10))
  }
})
// -> Error("not found")
pub fn unwrap_option(
  ro: Result(option.Option(a), e),
  default: a,
) -> Result(a, e)

Unwrap the Option inside Result, using a default for None. Returns the value if Some, the default if None, or preserves Error.

Examples

unwrap_option(Ok(Some(42)), 0)
// -> Ok(42)
unwrap_option(Ok(None), 0)
// -> Ok(0)
unwrap_option(Error("e"), 0)
// -> Error("e")
pub fn unwrap_option_lazy(
  ro: Result(option.Option(a), e),
  f: fn() -> a,
) -> Result(a, e)

Unwrap the Option inside Result, computing a default lazily for None. Returns the value if Some, computes default if None, or preserves Error.

Examples

unwrap_option_lazy(Ok(Some(42)), fn() { 0 })
// -> Ok(42)
unwrap_option_lazy(Ok(None), fn() { 100 })
// -> Ok(100)
unwrap_option_lazy(Error("e"), fn() { 0 })
// -> Error("e")
pub fn zip(
  ro1: Result(option.Option(a), e),
  ro2: Result(option.Option(b), e),
) -> Result(option.Option(#(a, b)), e)

Combine two ResultOptions into a tuple. Returns Error if either is Error, Ok(None) if either is Ok(None), or Ok(Some(#(a, b))) if both are Ok(Some).

Examples

zip(Ok(Some(1)), Ok(Some(2)))
// -> Ok(Some(#(1, 2)))
zip(Ok(Some(1)), Ok(None))
// -> Ok(None)
zip(Ok(Some(1)), Error("e"))
// -> Error("e")
pub fn zip3(
  ro1: Result(option.Option(a), e),
  ro2: Result(option.Option(b), e),
  ro3: Result(option.Option(c), e),
) -> Result(option.Option(#(a, b, c)), e)

Combine three ResultOptions into a tuple. Returns Error if any is Error, Ok(None) if any is Ok(None), or Ok(Some(#(a, b, c))) if all are Ok(Some).

Examples

zip3(Ok(Some(1)), Ok(Some(2)), Ok(Some(3)))
// -> Ok(Some(#(1, 2, 3)))
zip3(Ok(Some(1)), Ok(None), Ok(Some(3)))
// -> Ok(None)
zip3(Ok(Some(1)), Error("e"), Ok(Some(3)))
// -> Error("e")
Search Document