Types Module

Concrete type implementations with algebraic properties.

This module provides immutable data structures that implement the algebraic abstractions from katharos.algebra. These types enable type-safe, composable functional programming patterns.

Available types:
  • Maybe: Optional values without None checks

  • Result: Error handling without exceptions

  • ImmutableList: Immutable list with monadic operations

  • NonEmptyList: List guaranteed to have at least one element

  • IO: Lazy computation with side effects

  • MonoidMaybe: Maybe with monoid instance

  • Lazy: Lazy synchronous computation monad

  • UnwrapError: Raised when extracting an absent value

Each type implements appropriate algebraic abstractions (Functor, Applicative, Monad, etc.) and provides operators for convenient composition.

Maybe

final class katharos.types.Maybe(value=Nothing())[source]

Bases: Monad[Maybe[Any], A]

Optional value monad for type-safe null handling.

Maybe encapsulates a value that may or may not be present, eliminating None checks through functional composition. It implements the Monad, Applicative, and Functor interfaces.

A Maybe is in one of two states:

  • Just: contains a value of type A.

  • Nothing: contains no value.

Use Just() and Nothing() to construct values. Use is_just() and is_nothing() to check the state rather than isinstance checks.

Examples

>>> Maybe.Just(5).fmap(lambda x: x * 2)
Just(10)
>>> Maybe.Nothing().fmap(lambda x: x * 2)
Nothing()
>>> Maybe.Just(3) | (lambda x: Maybe.Just(x + 1))
Just(4)

Note

This class is @final and cannot be subclassed. Supports the | (bind) and ** (applicative apply) operators. Truthiness reflects the state: a Just is always truthy (even Just(0)), Nothing is falsy.

classmethod pure(x)[source]

Wrap a value in a Just.

Parameters:

x (TypeVar(T)) – The value to wrap.

Return type:

Maybe[TypeVar(T)]

Returns:

A Maybe containing the given value.

classmethod ret(x)[source]

Wrap a value in a Just.

Alias for pure(), provided to satisfy the Monad interface.

Parameters:

x (TypeVar(T)) – The value to wrap.

Return type:

Maybe[TypeVar(T)]

Returns:

A Maybe containing the given value.

classmethod Just(value)[source]
Overloads:
  • cls (type[Maybe[Never]]), value (S) → Maybe[S]

  • cls (type[Maybe[T]]), value (T) → Maybe[T]

Create a Maybe containing a value.

Parameters:

value (Any) – The value to wrap. Must not be a Nothing instance.

Returns:

A Maybe containing the given value.

Raises:

TypeError – If value is a _Nothing instance.

Return type:

Maybe[Any]

classmethod Nothing()[source]

Create an empty Maybe.

Subscript the class to fix the element type, e.g. Maybe[int].Nothing().

Return type:

Maybe[TypeVar(T)]

Returns:

An empty Maybe with no value.

__init__(value=Nothing())[source]

Initialize a Maybe with an optional value.

Parameters:

value (Union[TypeVar(A, covariant=True), _Nothing]) – The value to wrap. Defaults to nothing.

unwrap()[source]

Extract the wrapped value.

Return type:

TypeVar(A, covariant=True)

Returns:

The value contained in this Maybe.

Raises:

UnwrapError – If this Maybe is Nothing.

unwrap_or(default)[source]

Extract the wrapped value, or return a default if Nothing.

Parameters:

default (TypeVar(B)) – The value to return when this Maybe is Nothing.

Return type:

Union[TypeVar(A, covariant=True), TypeVar(B)]

Returns:

The wrapped value, or default if this Maybe is Nothing.

Examples

>>> Maybe.Just(5).unwrap_or(0)
5
>>> Maybe.Nothing().unwrap_or(0)
0
static from_optional(value)[source]

Convert an optional value into a Maybe.

None maps to Nothing; any other value is wrapped in a Just. Note that this means a Just(None) cannot be produced with this constructor — use Just() directly for that.

Parameters:

value (Optional[TypeVar(T)]) – The optional value to convert.

Return type:

Maybe[TypeVar(T)]

Returns:

A Just containing the value, or Nothing if the value is None.

Examples

>>> Maybe.from_optional(5)
Just(5)
>>> Maybe.from_optional(None)
Nothing()
to_optional()[source]

Convert this Maybe into an optional value.

The inverse of from_optional(). Note that Just(None) and Nothing both map to None.

Return type:

Optional[TypeVar(A, covariant=True)]

Returns:

The wrapped value, or None if this Maybe is Nothing.

Examples

>>> Maybe.Just(5).to_optional()
5
>>> Maybe.Nothing().to_optional() is None
True
fmap(f)[source]

Map a function over the wrapped value.

Parameters:

f (Callable[[TypeVar(A, covariant=True)], TypeVar(B)]) – Function to apply to the value.

Return type:

Maybe[TypeVar(B)]

Returns:

A Maybe containing the mapped value, or Nothing if this is Nothing.

ap(wrapped_funcs)[source]

Apply a function wrapped in a Maybe to this Maybe’s value.

Parameters:

wrapped_funcs (Applicative[Maybe, Callable[[TypeVar(A, covariant=True)], TypeVar(B)]]) – A Maybe containing a function to apply.

Return type:

Maybe[TypeVar(B)]

Returns:

A Maybe containing the result, or Nothing if either operand is Nothing.

bind(f)[source]

Chain a function that returns a Maybe.

Parameters:

f (Callable[[TypeVar(A, covariant=True)], Monad[Maybe, TypeVar(B)]]) – A function that takes the wrapped value and returns a Maybe.

Return type:

Maybe[TypeVar(B)]

Returns:

The result of applying f, or Nothing if this is Nothing.

is_just()[source]

Check if this Maybe contains a value.

Return type:

bool

Returns:

True if this is a Just, False if it is Nothing.

is_nothing()[source]

Check if this Maybe contains no value.

Return type:

bool

Returns:

True if this is Nothing, False if it is a Just.

__pow__(wrapped_funcs)[source]

Infix operator for applicative application (**).

Parameters:

wrapped_funcs (Applicative[Maybe, Callable[[TypeVar(A, covariant=True)], TypeVar(B)]]) – A Maybe containing a function to apply.

Return type:

Maybe[TypeVar(B)]

Returns:

A Maybe containing the result of applying the function.

__or__(f)[source]

Infix operator for monadic bind (|).

Parameters:

f (Callable[[TypeVar(A, covariant=True)], Monad[Maybe, TypeVar(B)]]) – A function that takes the wrapped value and returns a Maybe.

Return type:

Maybe[TypeVar(B)]

Returns:

The result of applying f, or Nothing if this is Nothing.

__eq__(other)[source]

Check equality with another Maybe.

Parameters:

other (object) – The object to compare with.

Return type:

bool

Returns:

True if both are the same state and hold equal values.

__bool__()[source]

Return the truthiness of this Maybe.

Truthiness reflects the state, not the wrapped value: a Just is always truthy, even Just(0) or Just(None).

Return type:

bool

Returns:

True if this is a Just, False if it is Nothing.

Examples

>>> bool(Maybe.Just(0))
True
>>> bool(Maybe.Nothing())
False
__repr__()[source]

Return the string representation of this Maybe.

Return type:

str

Returns:

Just(<value>) or Nothing().

__hash__()[source]

Return a hash of this Maybe.

Return type:

int

Returns:

Hash of the wrapped value, or a constant for Nothing.

MonoidMaybe

class katharos.types.MonoidMaybe(maybe)[source]

Bases: Monoid[MonoidMaybe[A]], Generic

A Monoid instance for optional semigroup values.

Lifts a semigroup A into an optional context: two Just values are combined using their semigroup @ operation; Nothing acts as the identity element, leaving the other operand unchanged.

Examples

>>> from katharos.types.list import NonEmptyList
>>> MonoidMaybe(Maybe.Just(NonEmptyList(1, [2]))) @ MonoidMaybe(Maybe.Just(NonEmptyList(3, [4])))
MonoidMaybe(Just(NonEmptyList([1, 2, 3, 4])))
>>> MonoidMaybe(Maybe.Just(NonEmptyList(1, [2]))) @ MonoidMaybe(Maybe.Nothing())
MonoidMaybe(Just(NonEmptyList([1, 2])))
classmethod identity()[source]

Return the identity element of the MonoidMaybe monoid.

Return type:

MonoidMaybe[TypeVar(A, bound= Semigroup)]

Returns:

A MonoidMaybe wrapping Nothing, which acts as the identity.

__init__(maybe)[source]

Initialize the MonoidMaybe with a Maybe value.

Parameters:

maybe (Maybe[TypeVar(A, bound= Semigroup)]) – The Maybe value to wrap.

property maybe: Maybe[A]

The wrapped Maybe value.

Returns:

The Maybe value held by this MonoidMaybe.

__eq__(other)[source]

Check equality with another MonoidMaybe.

Parameters:

other (object) – The object to compare with.

Return type:

bool

Returns:

True if other is a MonoidMaybe wrapping an equal Maybe.

__hash__()[source]

Return a hash of this MonoidMaybe.

Return type:

int

Returns:

Hash of the wrapped Maybe value.

op(other)[source]

Combine this MonoidMaybe with another using the semigroup operation.

Parameters:

other (MonoidMaybe[TypeVar(A, bound= Semigroup)]) – Another MonoidMaybe to combine with.

Return type:

MonoidMaybe[TypeVar(A, bound= Semigroup)]

Returns:

The other operand if this is Nothing; this operand if other is Nothing; otherwise a MonoidMaybe wrapping Just(self @ other).

__repr__()[source]

Return the string representation of this MonoidMaybe.

Return type:

str

Returns:

MonoidMaybe(<maybe>) with the wrapped Maybe.

Result

final class katharos.types.Result(value)[source]

Bases: Generic[E, A], Monad[Result[E, Any], A]

A Result monad for error handling without exceptions.

The Result type encapsulates a computation that can either succeed with a value of type A or fail with an exception of type E. It implements the Monad, Applicative, and Functor interfaces for composable error handling.

A Result can be in one of two states:

  • Success: Contains a value of type A (which may itself be an exception)

  • Failure: Contains an exception of type E

The success/failure distinction is tracked internally rather than by the type of the wrapped value, so an exception may be carried as a success value via Success()/pure() without being treated as a failure.

Type Parameters:

  • E: The type of the exception (must be a subclass of BaseException).

  • A: The type of the success value.

Examples

>>> success = Result.Success(42)
>>> success.is_success()
True
>>> success
Success(42)
>>> success.value
42
>>> failure = Result.Failure(ValueError("error"))
>>> failure.is_failure()
True
>>> failure
Failure(ValueError('error'))
>>> failure.error
ValueError('error')
>>> success.fmap(lambda x: x * 2)
Success(84)
>>> failure.fmap(lambda x: x * 2)
Failure(ValueError('error'))
>>> Result.Success(5) | (lambda x: Result.Success(x + 1))
Success(6)

Note

This class is marked as @final and cannot be subclassed. Use is_success() and is_failure() methods to check the state instead of type checking. Use Success() to create success values and Failure() to create failure values. Access success values with .value and failure errors with .error.

The class supports the following operators:

  • | (pipe): Monadic bind operation.

  • ** (power): Applicative application.

Truthiness reflects the state: a Success is always truthy (even Success(0)), a Failure is falsy.

classmethod pure(x)[source]

Wrap a value in a Success.

Parameters:

x (TypeVar(T)) – The value to wrap.

Return type:

Result[TypeVar(E, bound= BaseException, covariant=True), TypeVar(T)]

Returns:

A Success containing the value.

Raises:

TypeError – If the value is an internal error wrapper, which would masquerade as a Failure.

Note

The value may itself be an exception; it is still wrapped as a Success and is not treated as a Failure.

Examples

>>> Result.pure(42)
Success(42)
>>> Result.pure("hello")
Success('hello')
>>> Result.pure(ValueError("oops"))
Success(ValueError('oops'))
classmethod ret(x)[source]

Wrap a value in a Success.

Alias for pure(), provided to satisfy the Monad interface.

Parameters:

x (TypeVar(T)) – The value to wrap.

Return type:

Result[TypeVar(E, bound= BaseException, covariant=True), TypeVar(T)]

Returns:

A Success containing the value.

Examples

>>> Result.ret(42)
Success(42)
classmethod Success(x)[source]
Overloads:
  • cls (type[Result[Never, Never]]), x (S) → Result[Never, S]

  • cls (type[Result[Err, T]]), x (T) → Result[Err, T]

Create a Success result.

Parameters:

x (Any) – The value to wrap.

Returns:

A Success result containing the value.

Return type:

Result[Any, Any]

Examples

>>> Result.Success(42)
Success(42)
>>> Result.Success([1, 2, 3])
Success([1, 2, 3])
classmethod Failure(e)[source]
Overloads:
  • cls (type[Result[Never, Never]]), e (Err) → Result[Err, Never]

  • cls (type[Result[Never, Never]]), e (object) → Never

  • cls (type[Result[Err, T]]), e (Err) → Result[Err, T]

Create a Failure result.

Parameters:

e (Any) – The exception to wrap.

Returns:

A Failure result containing the exception.

Raises:

TypeError – If the value is not an exception.

Return type:

Result[Any, Any]

Examples

>>> Result.Failure(ValueError("bad input"))
Failure(ValueError('bad input'))
>>> Result.Failure(42)
Traceback (most recent call last):
    ...
TypeError: Cannot create a Result with a non-exception as the value
__init__(value)[source]

Initialize the Result.

Parameters:

value (Union[TypeVar(A, covariant=True), _ErrorWrapper[TypeVar(E, bound= BaseException, covariant=True)]]) – The value to wrap, either A or E.

property value: A

Get the success value of the Result.

Returns:

The success value.

Raises:

UnwrapError – If the Result is a Failure.

Examples

>>> Result.Success(42).value
42
>>> Result.Failure(ValueError("err")).value
Traceback (most recent call last):
    ...
UnwrapError: Cannot get the value of a Failure
property error: E

Get the error of the Result.

Returns:

The exception value.

Raises:

UnwrapError – If the Result is a Success.

Examples

>>> Result.Failure(ValueError("err")).error
ValueError('err')
>>> Result.Success(42).error
Traceback (most recent call last):
    ...
UnwrapError: Cannot get the error of a Success
unwrap()[source]

Unwrap the success value, raising an error if this is a Failure.

This method extracts the success value from a Success Result. If the Result is a Failure, it raises an UnwrapError with the original exception as the cause.

This is equivalent to accessing the .value property directly.

Return type:

TypeVar(A, covariant=True)

Returns:

The success value contained in this Result.

Raises:

UnwrapError – If the Result is a Failure, with the original exception as the cause chain.

Examples

>>> success = Result.Success(42)
>>> success.unwrap()
42
>>> failure = Result.Failure(ValueError("error"))
>>> failure.unwrap()
Traceback (most recent call last):
    ...
UnwrapError: Cannot get the value of a Failure
fmap(f)[source]

Map a function over the success value.

Parameters:

f (Callable[[TypeVar(A, covariant=True)], TypeVar(B)]) – Function to apply to the value.

Return type:

Result[TypeVar(E, bound= BaseException, covariant=True), TypeVar(B)]

Returns:

A new Result containing the mapped value, or the

original Failure unchanged.

Examples

>>> Result.Success(3).fmap(lambda x: x * 2)
Success(6)
>>> Result.Failure(ValueError("err")).fmap(lambda x: x * 2)
Failure(ValueError('err'))
>>> Result.Success("hi").fmap(str.upper)
Success('HI')
ap(wrapped_funcs)[source]

Apply a function wrapped in a Result to this Result.

Parameters:

wrapped_funcs (Applicative[Result[TypeVar(BE, bound= BaseException), Any], Callable[[TypeVar(A, covariant=True)], TypeVar(B)]]) – A Result containing the function to apply.

Return type:

Result[Union[TypeVar(BE, bound= BaseException), TypeVar(E, bound= BaseException, covariant=True)], TypeVar(B)]

Returns:

The result of applying the wrapped function to this

value. The error type BE comes from wrapped_funcs, not from self. Returns the first encountered Failure if either operand is a Failure.

Examples

>>> wrapped_fn = Result.Success(lambda x: x + 1)
>>> Result.Success(5).ap(wrapped_fn)
Success(6)
>>> Result.Failure(ValueError("err")).ap(wrapped_fn)
Failure(ValueError('err'))
>>> failure_fn = Result.Failure(TypeError("bad fn"))
>>> Result.Success(5).ap(failure_fn)
Failure(TypeError('bad fn'))
bind(f)[source]

Bind a function that returns a Result to this Result.

Parameters:

f (Callable[[TypeVar(A, covariant=True)], Monad[Result[TypeVar(BE, bound= BaseException), Any], TypeVar(B)]]) – A function that takes a value of type A and returns a Result[BE, B].

Return type:

Result[Union[TypeVar(BE, bound= BaseException), TypeVar(E, bound= BaseException, covariant=True)], TypeVar(B)]

Returns:

The result of applying f to the success value.

The error type BE comes from f’s return type, not from self. If self is a Failure, it is returned unchanged (re-typed as Result[BE, B]).

Examples

>>> Result.Success(5).bind(lambda x: Result.Success(x + 1))
Success(6)
>>> Result.Success(5).bind(lambda x: Result.Failure(ValueError("nope")))
Failure(ValueError('nope'))
>>> Result.Failure(ValueError("err")).bind(lambda x: Result.Success(x + 1))
Failure(ValueError('err'))
is_success()[source]

Check if this Result is a Success.

Return type:

bool

Returns:

True if this is a Success, False otherwise.

Examples

>>> Result.Success(42).is_success()
True
>>> Result.Failure(ValueError("err")).is_success()
False
is_failure()[source]

Check if this Result is a Failure.

Return type:

bool

Returns:

True if this is a Failure, False otherwise.

Examples

>>> Result.Failure(ValueError("err")).is_failure()
True
>>> Result.Success(42).is_failure()
False
__pow__(wrapped_funcs)[source]

Infix operator for applicative application (**).

Parameters:

wrapped_funcs (Applicative[Result[TypeVar(BE, bound= BaseException), Any], Callable[[TypeVar(A, covariant=True)], TypeVar(B)]]) – A Result containing the function to apply.

Return type:

Result[Union[TypeVar(BE, bound= BaseException), TypeVar(E, bound= BaseException, covariant=True)], TypeVar(B)]

Returns:

The result of applying the wrapped function to this

value. The error type BE comes from wrapped_funcs, not from self. Returns the first encountered Failure if either operand is a Failure.

Examples

>>> Result.Success(5) ** Result.Success(lambda x: x + 1)
Success(6)
>>> Result.Failure(ValueError("err")) ** Result.Success(lambda x: x + 1)
Failure(ValueError('err'))
__or__(f)[source]

Infix operator for monadic bind (|).

Parameters:

f (Callable[[TypeVar(A, covariant=True)], Monad[Result[TypeVar(BE, bound= BaseException), Any], TypeVar(B)]]) – A function that takes a value of type A and returns a Result[BE, B].

Return type:

Result[Union[TypeVar(BE, bound= BaseException), TypeVar(E, bound= BaseException, covariant=True)], TypeVar(B)]

Returns:

The result of applying f to the success value.

The error type BE comes from f’s return type, not from self. If self is a Failure, it is returned unchanged (re-typed as Result[BE, B]).

Examples

>>> Result.Success(5) | (lambda x: Result.Success(x + 1))
Success(6)
>>> (Result.Success(5)
...     | (lambda x: Result.Success(x * 2))
...     | (lambda x: Result.Success(x - 1)))
Success(9)
>>> Result.Failure(ValueError("err")) | (lambda x: Result.Success(x + 1))
Failure(ValueError('err'))
__repr__()[source]

Return the string representation of the Result.

Return type:

str

Returns:

Success(<value>) or Failure(<error>).

Examples

>>> repr(Result.Success(42))
'Success(42)'
>>> repr(Result.Failure(ValueError("err")))
"Failure(ValueError('err'))"
__eq__(value, /)[source]

Compare two Result objects for equality.

Two Results are equal if they are both Success with equal values, or both Failure with equal errors. A Success is never equal to a Failure, and a Result is never equal to a non-Result.

Failures compare by their wrapped exception. Note that exceptions use identity equality by default, so two distinct exceptions with the same message are not considered equal.

Parameters:

value (object) – The object to compare with.

Return type:

bool

Returns:

True if the objects are equal, False otherwise.

Examples

>>> Result.Success(42) == Result.Success(42)
True
>>> Result.Success(42) == Result.Success(43)
False
>>> err = ValueError("err")
>>> Result.Failure(err) == Result.Failure(err)
True
>>> Result.Success(42) == Result.Failure(ValueError("err"))
False
>>> Result.Success(42) == 42
False
__bool__()[source]

Return the truthiness of this Result.

Truthiness reflects the state, not the wrapped value: a Success is always truthy, even Success(0) or Success(None).

Return type:

bool

Returns:

True if this is a Success, False if it is a Failure.

Examples

>>> bool(Result.Success(0))
True
>>> bool(Result.Failure(ValueError("err")))
False
__hash__()[source]

Return the hash of the Result.

The hash is derived from the wrapped value (for a Success) or the wrapped exception (for a Failure). A Result is only hashable when its contents are hashable.

Return type:

int

Returns:

The hash of the Result.

Examples

>>> hash(Result.Success(42)) == hash(Result.Success(42))
True
static catch(ExceptionType)[source]

Decorator factory that converts a throwing function into one returning a Result.

Wraps the decorated function so that any exception of type ExceptionType raised during its execution is caught and returned as a Failure, while normal return values are wrapped in a Success. All other exception types propagate unchanged.

Parameters:

ExceptionType (type[TypeVar(Err, bound= BaseException)]) – The exception class to catch. Only instances of this exact type (or its subclasses) are intercepted.

Returns:

A decorator that transforms Callable[P, R] into Callable[P, Result[Err, R]].

Examples

Basic usage — catch a ValueError:

>>> @Result.catch(ValueError)
... def parse_int(s: str) -> int:
...     return int(s)
>>> parse_int("42")
Success(42)
>>> parse_int("bad")
Failure(ValueError("invalid literal for int() with base 10: 'bad'"))

Only the declared exception type is caught; others propagate:

>>> @Result.catch(ValueError)
... def risky(x: int) -> int:
...     if x < 0:
...         raise TypeError("negative")
...     return x
>>> risky(1)
Success(1)
>>> risky(-1)
Traceback (most recent call last):
    ...
TypeError: negative

Can be used with functions that take multiple arguments:

>>> @Result.catch(ZeroDivisionError)
... def divide(a: float, b: float) -> float:
...     return a / b
>>> divide(10.0, 2.0)
Success(5.0)
>>> divide(10.0, 0.0)
Failure(ZeroDivisionError('float division by zero'))

ImmutableList

class katharos.types.ImmutableList(elements)[source]

Bases: BaseImmutableList[T], Monad[ImmutableList[Any], T], Monoid[ImmutableList[T]]

A covariant immutable list with full monad and monoid support.

Provides an immutable wrapper around a Python list. The type parameter T is covariant, so ImmutableList[Child] is a subtype of ImmutableList[Parent] when Child is a subtype of Parent.

Instances are hashable and safe to use as dictionary keys or set members. All standard sequence operations are supported for read-only access.

Examples

>>> numbers = ImmutableList([1, 2, 3, 4, 5])
>>> len(numbers)
5
>>> 3 in numbers
True
>>> numbers[1]
2
>>> list(numbers)
[1, 2, 3, 4, 5]
>>> numbers + [6, 7]
ImmutableList([1, 2, 3, 4, 5, 6, 7])
__eq__(other)[source]

Check equality with another ImmutableList.

Parameters:

other (object) – The object to compare with.

Return type:

bool

Returns:

True if other is an ImmutableList with identical elements.

__hash__()[source]

Return a hash of the list contents.

Return type:

int

Returns:

Hash of the element tuple.

__repr__()[source]

Return the canonical string representation of this list.

Return type:

str

Returns:

ImmutableList([...]) with the element list.

__str__()[source]

Return the string form of the underlying element list.

Return type:

str

Returns:

The string representation of the internal Python list.

__add__(other)[source]

Concatenate this list with another iterable.

Parameters:

other (Iterable[TypeVar(T, covariant=True)]) – The elements to append.

Return type:

ImmutableList[TypeVar(T, covariant=True)]

Returns:

A new ImmutableList containing elements from both sequences.

classmethod identity()[source]

Return the identity element for the monoid operation.

Return type:

ImmutableList[TypeVar(T, covariant=True)]

Returns:

An empty ImmutableList.

classmethod pure(x)[source]

Wrap a single value in an ImmutableList.

Parameters:

x (TypeVar(T_1)) – The element to wrap.

Return type:

ImmutableList[TypeVar(T_1)]

Returns:

A singleton ImmutableList containing only x.

classmethod ret(x)[source]

Wrap a single value in an ImmutableList.

Alias for pure(), provided to satisfy the Monad interface.

Parameters:

x (TypeVar(T_1)) – The element to wrap.

Return type:

ImmutableList[TypeVar(T_1)]

Returns:

A singleton ImmutableList containing only x.

op(other)[source]

Combine this list with another using concatenation.

Parameters:

other (ImmutableList[TypeVar(T, covariant=True)]) – Another ImmutableList to concatenate with.

Return type:

ImmutableList[TypeVar(T, covariant=True)]

Returns:

A new ImmutableList containing elements from both lists.

fmap(f)[source]

Map a function over every element.

Parameters:

f (Callable[[TypeVar(T, covariant=True)], TypeVar(B)]) – A function to apply to each element.

Return type:

ImmutableList[TypeVar(B)]

Returns:

A new ImmutableList with the function applied to each element.

ap(wrapped_funcs)[source]

Apply each wrapped function to each element (cartesian product).

Parameters:

wrapped_funcs (Applicative[ImmutableList, Callable[[TypeVar(T, covariant=True)], TypeVar(B)]]) – An ImmutableList of functions to apply.

Return type:

ImmutableList[TypeVar(B)]

Returns:

A new ImmutableList with results of applying every function to every element.

bind(f)[source]

Flatmap this list with a function that returns a list (concatMap).

Parameters:

f (Callable[[TypeVar(T, covariant=True)], Monad[ImmutableList, TypeVar(B)]]) – A function that takes an element and returns an ImmutableList.

Return type:

ImmutableList[TypeVar(B)]

Returns:

A new ImmutableList with the results of all returned lists concatenated.

__matmul__(other)[source]

Infix operator for the semigroup concatenation (@).

Parameters:

other (ImmutableList[TypeVar(T, covariant=True)]) – Another ImmutableList to concatenate with.

Return type:

ImmutableList[TypeVar(T, covariant=True)]

Returns:

A new ImmutableList containing all elements from both lists.

__pow__(wrapped_funcs)[source]

Infix operator for applicative application (**).

Parameters:

wrapped_funcs (Applicative[ImmutableList, Callable[[TypeVar(T, covariant=True)], TypeVar(B)]]) – An ImmutableList of functions to apply.

Return type:

ImmutableList[TypeVar(B)]

Returns:

A new ImmutableList with results of applying every function to every element.

__or__(f)[source]

Infix operator for monadic bind (|).

Parameters:

f (Callable[[TypeVar(T, covariant=True)], Monad[ImmutableList, TypeVar(B)]]) – A function that takes an element and returns an ImmutableList.

Return type:

ImmutableList[TypeVar(B)]

Returns:

A new ImmutableList with all returned lists concatenated.

NonEmptyList

class katharos.types.NonEmptyList(head, tail)[source]

Bases: BaseImmutableList[T], Monad[NonEmptyList[Any], T], Semigroup[NonEmptyList[T]]

An immutable list guaranteed to contain at least one element.

NonEmptyList provides the same functional interface as ImmutableList — including Monad and Semigroup — without a Monoid instance (no empty list is representable).

Access the first element with head and the remaining elements with tail.

__init__(head, tail)[source]

Create a non-empty list with at least one element.

Parameters:
  • head (TypeVar(T, covariant=True)) – The first (guaranteed) element.

  • tail (list[TypeVar(T, covariant=True)]) – The remaining elements (may be empty).

__eq__(other)[source]

Check equality with another NonEmptyList.

Parameters:

other (object) – The object to compare with.

Return type:

bool

Returns:

True if other is a NonEmptyList with identical elements.

__hash__()[source]

Return a hash of the list contents.

Return type:

int

Returns:

Hash of the element tuple.

__add__(other)[source]

Concatenate this list with another iterable.

Parameters:

other (Iterable[TypeVar(T, covariant=True)]) – The elements to append.

Return type:

NonEmptyList[TypeVar(T, covariant=True)]

Returns:

A new NonEmptyList containing all elements from both sequences.

__repr__()[source]

Return a string representation of this list.

Return type:

str

Returns:

NonEmptyList([...]) with the element list.

property head: T

The first element of the list.

Returns:

The first element.

property tail: list[T]

All elements after the first.

Returns:

A plain list of the remaining elements (may be empty).

classmethod pure(x)[source]

Wrap a single value in a NonEmptyList.

Parameters:

x (TypeVar(A)) – The element to wrap.

Return type:

NonEmptyList[TypeVar(A)]

Returns:

A singleton NonEmptyList containing only x.

classmethod ret(x)[source]

Wrap a single value in a NonEmptyList.

Alias for pure(), provided to satisfy the Monad interface.

Parameters:

x (TypeVar(A)) – The element to wrap.

Return type:

NonEmptyList[TypeVar(A)]

Returns:

A singleton NonEmptyList containing only x.

fmap(f)[source]

Map a function over every element.

Parameters:

f (Callable[[TypeVar(T, covariant=True)], TypeVar(B)]) – A function to apply to each element.

Return type:

NonEmptyList[TypeVar(B)]

Returns:

A new NonEmptyList with the function applied to each element.

ap(wrapped_funcs)[source]

Apply each wrapped function to each element (cartesian product).

Parameters:

wrapped_funcs (Applicative[NonEmptyList, Callable[[TypeVar(T, covariant=True)], TypeVar(B)]]) – A NonEmptyList of functions to apply.

Return type:

NonEmptyList[TypeVar(B)]

Returns:

A new NonEmptyList with results of applying every function to every element.

bind(f)[source]

Flatmap this list with a function that returns a NonEmptyList (concatMap).

Parameters:

f (Callable[[TypeVar(T, covariant=True)], Monad[NonEmptyList, TypeVar(B)]]) – A function that takes an element and returns a NonEmptyList.

Return type:

NonEmptyList[TypeVar(B)]

Returns:

A new NonEmptyList with the results of all returned lists concatenated.

op(other)[source]

Concatenate this list with another NonEmptyList.

Parameters:

other (NonEmptyList[TypeVar(T, covariant=True)]) – Another NonEmptyList to combine with.

Return type:

NonEmptyList[TypeVar(T, covariant=True)]

Returns:

A new NonEmptyList containing all elements from both lists.

IO

class katharos.types.IO(value, io_func=FunctionWithSideEffect(f=<function FunctionWithSideEffect.no_op.<locals>.<lambda>>, description='No operation'))[source]

Bases: Monad[IO[Any], A]

Lazy wrapper for a value with deferred side-effect execution.

IO encapsulates a value together with an optional side-effect function. The side effect is not run until execute() is called, preserving referential transparency for pure callers.

Use pure() or ret() to create an IO with no side effect, fmap() to transform the wrapped value, and | (or bind()) to sequence computations. Call execute() to run accumulated side effects.

classmethod pure(x)[source]

Wrap a plain value in an IO action with no side effect.

Parameters:

x (TypeVar(T)) – The value to wrap.

Return type:

IO[TypeVar(T)]

Returns:

An IO action containing the given value.

classmethod ret(x)[source]

Wrap a plain value in an IO action with no side effect.

Alias for pure(), provided to satisfy the Monad interface.

Parameters:

x (TypeVar(T)) – The value to wrap.

Return type:

IO[TypeVar(T)]

Returns:

An IO action containing the given value.

__init__(value, io_func=FunctionWithSideEffect(f=<function FunctionWithSideEffect.no_op.<locals>.<lambda>>, description='No operation'))[source]

Initialize an IO action.

Parameters:
  • value (TypeVar(A, covariant=True)) – The value to wrap.

  • io_func (FunctionWithSideEffect) – The side-effect function to defer. Defaults to a no-op.

io_func: FunctionWithSideEffect
property value: A

The value inside this IO action.

Returns:

The wrapped value.

execute()[source]

Execute the accumulated side effects.

Return type:

None

fmap(f)[source]

Map a function over the wrapped value.

Parameters:

f (Callable[[TypeVar(A, covariant=True)], TypeVar(B)]) – Function to apply to the value.

Return type:

IO[TypeVar(B)]

Returns:

A new IO action containing the mapped value.

ap(wrapped_funcs)[source]

Apply a function wrapped in IO to this IO action.

Parameters:

wrapped_funcs (Applicative[IO, Callable[[TypeVar(A, covariant=True)], TypeVar(B)]]) – An IO action containing a function to apply.

Return type:

IO[TypeVar(B)]

Returns:

A new IO action with the result of applying the function.

bind(f)[source]

Chain this IO action with a function that returns another IO action.

Parameters:

f (Callable[[TypeVar(A, covariant=True)], Monad[IO, TypeVar(B)]]) – A function that takes the wrapped value and returns an IO action.

Return type:

IO[TypeVar(B)]

Returns:

A new IO action combining this action’s side effects with those of the result of applying f.

then(other)[source]

Sequence two IO actions, accumulating both side effects.

Parameters:

other (Monad[IO, TypeVar(B)]) – The IO action to sequence after this one.

Return type:

IO[TypeVar(B)]

Returns:

A new IO action that carries both side effects and holds the value of other.

__pow__(wrapped_funcs)[source]

Infix operator for applicative application (**).

Parameters:

wrapped_funcs (Applicative[IO, Callable[[TypeVar(A, covariant=True)], TypeVar(B)]]) – An IO action containing a function to apply.

Return type:

IO[TypeVar(B)]

Returns:

A new IO action with the result of applying the function.

__or__(f)[source]

Infix operator for monadic bind (|).

Parameters:

f (Callable[[TypeVar(A, covariant=True)], Monad[IO, TypeVar(B)]]) – A function that takes the wrapped value and returns an IO action.

Return type:

IO[TypeVar(B)]

Returns:

A new IO action with the result of applying f.

__rshift__(other)[source]

Infix operator for sequencing IO actions (>>).

Sequences this IO action with another, accumulating both side effects and discarding this action’s value.

Parameters:

other (Monad[IO, TypeVar(B)]) – The IO action to sequence after this one.

Return type:

IO[TypeVar(B)]

Returns:

A new IO action carrying both side effects and holding other’s value.

UnwrapError

class katharos.types.UnwrapError[source]

Bases: Exception

Raised when extracting a value that is absent.

Covers unwrapping a Nothing Maybe, getting the value of a Failure Result, or getting the error of a Success Result.