Skip to content

apfel.container.result

A container that holds either a success or a failure.

See Result and Either.

A Result has two possible states, Ok or Err. Ok means a successful value is present, and Err means a failure value is present.

This module also provides a caught decorator, which wraps a partial function to a total function returning a Result.

The Result class, and the ok, err, and caught functions are exposed in the package namespace.

Rationale

Python raise is easily missed, since the gradual typing system does not support checked exceptions. An alternative is to return nullable error flags, which is cumbersome to work with.

Implementation

Result’s APIs are based on the Rust Result, and the comparison table is provided below.

Reference Result Counterpart
and and_
and_then and_then
as_deref /
as_deref_mut /
as_mut /
as_ref /
cloned -
copied /
err err
expect expect
expect_err expect_err
flatten flatten
inspect ~tap
inspect_err ~tap_err
into_err -
into_ok -
is_err is_err
is_err_and is_err_and
is_ok is_ok
is_ok_and is_ok_and
iter -
iter_mut /
map map
map_err map_err
map_or map_or
map_or_default /
map_or_else map_or_else
ok ok
or or_
or_else or_else
transpose ~transpose
unwrap unwrap
unwrap_err unwrap_err
unwrap_err_unchecked unwrap_err_unchecked
unwrap_or unwrap_or
unwrap_or_default /
unwrap_or_else unwrap_or_else
unwrap_unchecked unwrap_unchecked

API#

Classes

NameDescription
ResultA container that holds either a success or a failure.
caughtA decorator that wraps a partial function to a total function returning a Result.
errConstruct an Err value.
okConstruct an Ok value.

Resultclass#

class Result(value: T, /, *, is_ok: bool = True)

Bases: Monad

A container that holds either a success or a failure. See module-level documentation for more details.

This class is exposed in the package namespace.

__slots__attributeclass attributeinstance attribute#

__slots__ = ('_val', '_is_ok')

__and__method#

def __and__(other: Self) -> Self

__bool__method#

def __bool__() -> bool

__class_getitem__method#

def __class_getitem__(item)

__eq__method#

def __eq__(other: Self, /) -> bool

__hash__method#

def __hash__() -> int

__init__method#

def __init__(value: T, /, *, is_ok: bool = True)

__or__method#

def __or__(other: Self) -> Self

__repr__method#

def __repr__()

__str__method#

def __str__()

and_method#

def and_(other: Self, /) -> Self

If the value is Ok, return a shallow copy of the other Result. Otherwise, return a new Err of type Result[T, E].

and_thenmethod#

def and_then(func: Callable[[T], Result[U, E]], /) -> Result[U, E]

If the value is Ok, apply a function that maps the inner value to a Result[U, E] value. Otherwise, return Err of type Result[U, E].

applymethod#

def apply(func: Result[Callable[[T], U], E], /) -> Result[U, E]

Implementation of Applicative.apply. Applies the callable wrapped within a Result to the inner value, if both are Ok.

bindmethod#

def bind(func: Callable[[T], Result[U, E]], /) -> Result[U, E]

Implementation of Monad.bind. Alias of and_then.

donemethod#

def done() -> tuple[T, None] | tuple[None, E]

errmethod#

def err() -> Maybe[E]

Convert a Result[T, E] to a Maybe[E].

expectmethod#

def expect(message: str, /) -> T

Unwrap the inner Ok value, if any. Otherwise, raise a ValueError with a custom message.

expect_errmethod#

def expect_err(message: str, /) -> E

Unwrap the inner Err value, if any. Otherwise, raise a ValueError with a custom message.

flattenmethod#

def flatten() -> Result[T_, E]

Flatten a nested Result (Result[Result[T, E], E]) value for one level (Result[T, E]).

is_errmethod#

def is_err() -> bool

Check if the value is an Err.

is_err_andmethod#

def is_err_and(pred: Callable[[E], bool], /) -> bool

Check if the value is an Err and satisfies the predicate.

is_okmethod#

def is_ok() -> bool

Check if the value is an Ok.

is_ok_andmethod#

def is_ok_and(pred: Callable[[T], bool], /) -> bool

Check if the value is an Ok and satisfies the predicate.

make_errmethodclassmethod#

def make_err(value: E, /) -> Result[T, E]

Construct an Err value.

make_okmethodclassmethod#

def make_ok(value: T, /) -> Result[T, E]

Construct an Ok value.

mapmethod#

def map(func: Callable[[T], U], /) -> Result[U, E]

Map a Result[T, E] to Result[U, E] by applying a function to a contained Ok value, leaving an Err value untouched.

map_errmethod#

def map_err(func: Callable[[E], F], /) -> Result[T, F]

Map a Result[T, E] to Result[T, F] by applying a function to a contained Err value, leaving an Ok value untouched.

map_ormethod#

def map_or(default: U, func: Callable[[T], U]) -> U

Apply a function to a contained Ok value, or return a provided default value.

map_or_elsemethod#

def map_or_else(default: Callable[[E], U], func: Callable[[T], U]) -> U

Map a Result[T, E] to U by applying a function to a contained Ok value, or a fallback function to a contained Err value.

okmethod#

def ok() -> Maybe[T]

Convert a Result[T, E] to a Maybe[T].

or_method#

def or_(other: Self, /) -> Self

If the value is Err, return a shallow copy of the other Result. Otherwise, return a new Ok of type Result[T, F].

or_elsemethod#

def or_else(func: Callable[[E], Self], /) -> Self

Return a shallow copy of the Result if it contains an Ok value, otherwise call a function to get a result.

puremethodclassmethod#

def pure(value: T, /) -> Result[T, E]

Implementation of Applicative.pure, which is equivalent to Result.make_ok.

tapmethod#

def tap(func: Callable[[T], Any], /) -> Self

Call a function with the contained Ok value if it exists.

Unlike Result::inspect, this method does not require the function to return None.

some_ok = ok(5)
some_err = err("error")
some_ok.tap(print) # prints: 5
some_err.tap(print) # prints nothing

tap_errmethod#

def tap_err(func: Callable[[E], Any], /) -> Self

Call a function with the contained Err value if it exists.

throwmethod#

def throw() -> T

Raise the contained exception if it is an Err. Otherwise, return the inner Ok value.

transposemethod#

def transpose() -> Maybe[Result[U, E]]

Transpose a Result of a Maybe into a Maybe of a Result. Result[Maybe[T], E] -> Maybe[Result[T, E]]

unwrapmethod#

def unwrap() -> T

Unwrap the inner Ok value, if any. Otherwise, raise a ValueError.

unwrap_errmethod#

def unwrap_err() -> E

Unwrap the inner Err value, if any. Otherwise, raise a ValueError.

unwrap_err_uncheckedmethod#

def unwrap_err_unchecked() -> E

Return the inner Err value without checking if it is an Err.

unwrap_ormethod#

def unwrap_or(default: T, /) -> T

Unwrap the inner Ok value, or return a default value if contains an Err.

unwrap_or_elsemethod#

def unwrap_or_else(func: Callable[[E], T], /) -> T

Unwrap the inner Ok value, or return a value computed by a function if contains an Err.

unwrap_uncheckedmethod#

def unwrap_unchecked() -> T

Return the inner value without checking if it is an Ok or Err.

caughtclass#

class caught

A decorator that wraps a partial function to a total function returning a Result.

It supports multiple usages:

  • Use as a decorator without arguments (@caught) to catch all exceptions.
  • Use as a decorator with specific exception types (either type union @caught(ExceptionA | ExceptionB) or args @caught(ExceptionA, ExceptionB)) to catch only those exceptions.
  • Use as a higher-order function by passing the target function (caught(func)) to catch all exceptions.
  • Use as a higher-order function with specific exception types as args (caught(func, ExceptionA, ExceptionB)) to catch only those exceptions.
  • Use generic syntax to provide type hints (@caught[ExceptionA], @caught[ExceptionA](), caught[ExceptionA]()), without affecting runtime behavior.

This function is exposed in the package namespace.

@caught(ZeroDivisionError)
def divide(a: float, b: float) -> float:
return a / b
divide(4, 2) # Ok(2.0)
divide(4, 0) # Err(ZeroDivisionError)

__class_getitem__method#

def __class_getitem__(item: type[F]) -> type[caught[F, T]]

__new__method#

def __new__(first=None, /, *exceptions: type[Es]) -> Callable[[Callable[P, U]], Callable[P, Result[U, E]]] | Callable[[Callable[P, U]], Callable[P, Result[U, F]]] | Callable[[Callable[P, U]], Callable[P, Result[U, E0 | Es]]] | Callable[P, Result[U, Es]] | Callable[P, Result[U, E]]

errclass#

class err

Construct an Err value.

This function is exposed in the package namespace.

some_err = err("Something went wrong")
match some_err:
case ok(value):
print(f"Got an Ok with value: {value}")
case err(error):
print(f"Got an Err with error: {error}")
# Output: Got an Err with error: Something went wrong

__match_args__attributeclass attributeinstance attribute#

__match_args__ = ('_val')

__slots__attributeclass attributeinstance attribute#

__slots__ = ()

__class_getitem__method#

def __class_getitem__(item)

__instancecheck__methodclassmethod#

def __instancecheck__(instance)

__new__method#

def __new__(value: E, /) -> Result[T, E]

okclass#

class ok

Construct an Ok value.

This function is exposed in the package namespace.

some_ok = ok(42)
match some_ok:
case ok(value):
print(f"Got an Ok with value: {value}")
case err(error):
print(f"Got an Err with error: {error}")
# Output: Got an Ok with value: 42

__match_args__attributeclass attributeinstance attribute#

__match_args__ = ('_val')

__slots__attributeclass attributeinstance attribute#

__slots__ = ()

__class_getitem__method#

def __class_getitem__(item)

__instancecheck__methodclassmethod#

def __instancecheck__(instance)

__new__method#

def __new__(value: T, /) -> Result[T, E]