Functional programming utilities and monadic types.

This module provides functional programming constructs including monads, lazy evaluation, and caching utilities. It implements the monad pattern for composing computations in a functional style, with support for chaining operations and deferred evaluation.

Examples

Using Maybe for optional value handling:

from deluxe.functional import Maybe

def parse_int(value: str) -> Maybe[int]:
    try:
        return Maybe.pure(int(value))
    except ValueError:
        return Maybe()

result = parse_int("42")
match result:
    case Maybe(value):
        print(f"Parsed: {value}")
    case _:
        print("Invalid input")

Using Lazy for deferred computation:

from deluxe.functional import Lazy

def expensive_computation() -> int:
    print("Computing...")
    return 42

# Computation not executed yet
lazy_value = Lazy(expensive_computation, int)

# Computation executed here
result = lazy_value.unwrap()  # Prints "Computing..."

Using MaybeCallable with enumerations:

from enum import Enum, member
from deluxe.functional import MaybeCallable

class Key(MaybeCallable[bytes]):
    def __call__(self, *args: bytes) -> bytes:
        return self._callable_(*args)

class KeyStroke(Key[bytes], Enum):
    @member
    @staticmethod
    def Ctrl(key: bytes) -> str:
        return f"C-{key.decode()}"

    Space = b"Space"

See also

Module Contents

Classes

cached_property

Similar to property(), with the addition of…

Monad

Protocol defining the interface for monadic types.

Maybe

Maybe class.

Lazy

Implementation of the Monad protocol…

MaybeCallable

Monad wrapping up a type or a callable…

class cached_property(func: collections.abc.Callable[[Any], _T_co])[source]

Extends: Generic[_T_co]

Similar to property(), with the addition of caching.

Transform a method of a class into a property whose value is computed once and then cached as a normal attribute for the life of the instance. Useful for expensive computed properties of instances that are otherwise effectively immutable.

Keys Differences from functools.cached_property:

  • support pure python class as well as mypyc compiled Native and Non-Native extension class.

  • prevent reset or deletion of the property on the instance

  • allow usage in class with or without writable __dict__ (eg., class with __slots__)

func : collections.abc.Callable[[Any], _T_co]
attrname : str
class Monad[source]

Extends: Protocol[_T]

Protocol defining the interface for monadic types.

A monad is a design pattern from functional programming that provides a way to structure computations. It defines a standard interface for values that can be “wrapped” in a context, enabling consistent handling of computations that might involve side effects, error handling, or delayed evaluation.

The protocol requires implementations to provide methods for wrapping values in the monadic context (pure()), transforming wrapped values (map()), and chaining computations that produce monadic results (bind()).

Examples

Basic usage with the Lazy implementation:

from deluxe.functional import Lazy

# Wrap a value using pure
lazy_value = Lazy.pure(42)

# Transform the value using map
lazy_doubled = lazy_value.map(lambda x: x * 2)
print(lazy_doubled.unwrap())  # 84

# Chain computations using bind
def to_lazy(x: int) -> Lazy[str]:
    return Lazy.pure(str(x))

lazy_string = lazy_value.bind(to_lazy)
print(lazy_string.unwrap())  # "42"
Protocol Methods:
  • pure(): Wrap a plain value in the monadic context.

  • map(): Apply a function to the wrapped value (functorial map).

  • bind(): Chain a function that returns cast(_OST, a monadic value.)

  • join(): Flatten a monad of monads into a single monad.

  • unwrap(): Extract the wrapped value from the monadic context.

  • __call__(): Alias for unwrap(), allowing monads to be called.

See also

classmethod pure(value: _T) Self[source]

Wrap a plain value into the monadic context.

This is a class method that creates a new monadic instance containing the given plain value. This is the primary way to enter the monadic context from a non-monadic value.

Parameters:
value: _T

The plain value to wrap in the monadic context.

Returns:

A monadic instance of the same type as cls containing the wrapped value.

map(func: collections.abc.Callable[[_T], _U], *args: Any, **kwds: Any) Monad[_U][source]

Apply a function to the wrapped value (functorial map).

This method transforms the value inside the monadic context by applying the given function. It preserves the monadic structure, returning a new monad containing the transformed value.

The map method implements the functor pattern, which is typically derived from bind() and pure() in functional programming theory.

Parameters:
func: collections.abc.Callable[[_T], _U]

A callable that receives the wrapped value and returns a transformed value of a (potentially different) type.

*args: Any

Additional positional arguments to pass to func.

**kwds: Any

Additional keyword arguments to pass to func.

Returns:

A monadic instance wrapping the result of func, whose type matches the return type of func.

bind(func: collections.abc.Callable[[_T], Monad[_U]], *args: Any, **kwds: Any) Monad[_U][source]

Chain a function that returns a monadic value.

This method allows for chaining computations that produce monadic results. It applies the function to the wrapped value, which itself returns a monad, and then flattens the result to avoid nested monads.

The bind operation (also known as flatMap or >>= in other languages) is the fundamental operation that gives monads their power for sequencing computations.

Parameters:
func: collections.abc.Callable[[_T], Monad[_U]]

A callable that receives the wrapped value and returns a monadic instance wrapping a value of a (potentially different) type.

*args: Any

Additional positional arguments to pass to func.

**kwds: Any

Additional keyword arguments to pass to func.

Returns:

A monadic instance wrapping the result of func, whose type matches the return type of func, with the nested monadic structure flattened.

join() Self[source]

Flatten a monad of monads into a single monad.

This method unwraps one level of monadic structure, which is useful when dealing with nested monadic contexts. For monads wrapping other monads of the same type, join provides a way to reduce the nesting level.

The join operation is related to bind and is defined as: m.join() == m.bind(lambda x: x).

Returns:

A monadic instance with one level of nesting removed.

unwrap() _T[source]

Extract the wrapped value from the monadic context.

This method returns the plain value contained within the monadic structure. This operation is sometimes called run or value in other monad implementations.

Note that not all monads support this operation, as some monadic contexts (like IO monads) are meant to remain encapsulated to maintain referential transparency.

Returns:

The plain value that was wrapped in the monadic context.

class Maybe(value: _T = Unset)[source]

Extends: Generic[_T]

Maybe class.

Usage

Note

For pattern matching against deluxe.types.Unset you can’t use Maybe(Unset), this won’t work at runtime nor statically with typechecker. You should instead import the deluxe.types module and use Maybe(types.Unset).

property type : type[_T]

Return the Python type of the wrapped value.

Returns:

The type of the value stored in this Maybe instance.

classmethod pure(value: _T) Self[source]

Wrap a plain value into the Maybe monadic context.

Creates a new Maybe instance containing the given value. This is the primary way to enter the Maybe context from a non-monadic value.

Parameters:
value: _T

The plain value to wrap in the Maybe context.

Returns:

A Maybe instance containing the wrapped value.

Raises:

ValueError – If value is deluxe.types.Unset.

Examples:

>>> from deluxe.functional import Maybe
>>> Maybe.pure(42)
Maybe[int](42)
>>> Maybe.pure("hello")
Maybe[str](hello)
map(func: collections.abc.Callable[[_T], _U], *_args: Any, **_kwds: Any) Maybe[_U][source]

Apply a function to the wrapped value (functorial map).

This method transforms the value inside the Maybe context by applying the given function. It preserves the monadic structure, returning a new Maybe containing the transformed value.

If this Maybe is empty (contains deluxe.types.Unset), the function is not called and an empty Maybe is returned.

Parameters:
func: collections.abc.Callable[[_T], _U]

A callable that receives the wrapped value and returns a transformed value of a (potentially different) type.

Returns:

A new Maybe wrapping the result of func, whose type matches the return type of func. Returns an empty Maybe if this instance is empty.

Examples:

>>> from deluxe.functional import Maybe
>>> Maybe.pure(5).map(lambda x: x * 2)
Maybe[int](10)
>>> Maybe().map(lambda x: x * 2)
Maybe[NoneType](Unset)
bind(func: collections.abc.Callable[[_T], Maybe[_U]], *_args: Any, **_kwds: Any) Maybe[_U][source]

Chain a function that returns a Maybe value.

This method allows for chaining computations that produce Maybe results. It applies the function to the wrapped value, which itself returns a Maybe, and then flattens the result to avoid nested monads.

If this Maybe is empty (contains deluxe.types.Unset), the function is not called and an empty Maybe is returned.

The bind operation (also known as flatMap or >>= in other languages) is the fundamental operation that gives monads their power for sequencing computations.

Parameters:
func: collections.abc.Callable[[_T], Maybe[_U]]

A callable that receives the wrapped value and returns a Maybe wrapping a value of a (potentially different) type.

Returns:

A new Maybe wrapping the result of func, whose type matches the return type of func, with the nested Maybe structure flattened.

Examples:

>>> from deluxe.functional import Maybe
>>> def double_if_positive(x: int) -> Maybe[int]:
...     return Maybe(x * 2) if x > 0 else Maybe()
>>> Maybe.pure(5).bind(double_if_positive)
Maybe[int](10)
>>> Maybe.pure(-1).bind(double_if_positive)
Maybe[NoneType](Unset)
join() Self[source]

Flatten a nested Maybe into a single Maybe.

This method unwraps one level of monadic structure, which is useful when dealing with nested Maybe contexts. It extracts the value and re-wraps it in a fresh Maybe.

The join operation is related to bind and is defined as: m.join() == m.bind(lambda x: x).

Returns:

A Maybe instance with one level of nesting removed.

Examples:

>>> from deluxe.functional import Maybe
>>> nested = Maybe(Maybe(42))
>>> nested.join()
Maybe[int](42)
unwrap() _T[source]

Extract the wrapped value from the Maybe context.

This method returns the plain value contained within the monadic structure. If this Maybe is empty, it returns deluxe.types.Unset.

Returns:

The plain value of type _T that was wrapped in the Maybe context, or deluxe.types.Unset if empty.

Examples:

>>> from deluxe.functional import Maybe
>>> Maybe.pure(42).unwrap()
42
>>> Maybe().unwrap()
Unset
class Lazy(value: collections.abc.Callable[[], _T], type: Lazy.__init__.type[_T])[source]

Extends: Generic[_T]

Implementation of the Monad protocol for lazy evaluation.

The Lazy class wraps a callable that defers computation until explicitly requested. This enables lazy evaluation, where computations are only performed when their results are needed, and results are cached across multiple accesses.

The __set_name__() method is present solely to allow usage of Lazy as enumeration’s member in deluxe.enums.Enum.

Examples

Creating a lazy value from a callable:

from deluxe.functional import Lazy

def expensive_computation() -> int:
    print("Computing...")
    return 42

lazy_value = Lazy(expensive_computation, int)
# Nothing printed yet - computation not executed

result = lazy_value.unwrap()  # Prints "Computing..."
# result is now 42

result2 = lazy_value.unwrap()  # Prints again - result is not cached

Using pure() to wrap static values:

from deluxe.functional import Lazy

lazy_int = Lazy.pure(42)
print(lazy_int.unwrap())  # 42

Chaining transformations with map():

from deluxe.functional import Lazy

lazy_value = Lazy.pure(5)
lazy_doubled = lazy_value.map(lambda x: x * 2, int)
lazy_squared = lazy_doubled.map(lambda x: x * x, int)
print(lazy_squared.unwrap())  # 100

Chaining monadic computations with bind():

from deluxe.functional import Lazy

def parse_int(s: str) -> Lazy[int]:
    return Lazy.pure(int(s))

lazy_str = Lazy.pure("42")
lazy_int = lazy_str.bind(parse_int, int)
print(lazy_int.unwrap())  # 42

Calling lazy values as functions:

from deluxe.functional import Lazy

lazy_value = Lazy.pure(10)
result = lazy_value()  # Equivalent to lazy_value.unwrap()
print(result)  # 10

Note

While this class has a __set_name__() method, it is not a descriptor. The method is used only to track metadata (__objclass__ and _name_) when instances are assigned as class attributes. To access the value, explicitly call unwrap() or use the callable syntax instance().

Parameters:
value: collections.abc.Callable[[], _T]

A callable (typically a function or lambda) that will be executed when the lazy value is unwrapped.

type: Lazy.__init__.type[_T]

The type of the value that will be produced when value is called. This is used for type annotations and can be different from the callable’s actual return type.

Note

The value callable is not executed during initialization. The computation is deferred until unwrap() or __call__() is invoked.

See also

property type : type[_T]

Return the Python type that this Lazy instance will produce.

Returns:

The type annotation of the value that will be produced when this lazy computation is evaluated.

Examples

>>> from deluxe.functional import Lazy
>>> lazy_int = Lazy(lambda: 42, int)
>>> lazy_int.type
<class 'int'>
classmethod pure(value: _U) Lazy[_U][source]

Wrap a plain value into the lazy monadic context.

Creates a Lazy instance that will always return the given static value when unwrapped. This is the primary way to create a lazy value from a non-callable.

Parameters:
value: _U

The plain value to wrap in the lazy context.

Returns:

A Lazy instance that will produce value when unwrapped.

Examples

>>> from deluxe.functional import Lazy
>>> lazy_int = Lazy.pure(42)
>>> lazy_int.unwrap()
42
map(func: collections.abc.Callable[[_T], _U], type: Lazy.map.type[_U]) Lazy[_U][source]

Apply a function to the lazy value using functorial map.

Creates a new Lazy instance that will apply func to the result of this lazy computation when unwrapped. This allows for chaining transformations in a lazy context.

Parameters:
func: collections.abc.Callable[[_T], _U]

A callable that receives the unwrapped value and returns a transformed value of a (potentially different) type.

type: Lazy.map.type[_U]

The type of the value that func will return.

Returns:

A new Lazy instance that will produce func(value) when unwrapped, where value is the result of unwrapping this instance.

Examples

>>> from deluxe.functional import Lazy
>>> lazy_value = Lazy.pure(5)
>>> lazy_doubled = lazy_value.map(lambda x: x * 2, int)
>>> lazy_doubled.unwrap()
10
bind(func: collections.abc.Callable[[_T], Lazy[_U]], type: Lazy.bind.type[_U]) Lazy[_U][source]

Chain a function that returns a lazy value using monadic bind.

Applies func to the result of this lazy computation and returns the resulting Lazy instance directly. This allows for chaining computations where each step produces a new lazy context.

Parameters:
func: collections.abc.Callable[[_T], Lazy[_U]]

A callable that receives the unwrapped value and returns a Lazy wrapping a value of a (potentially different) type.

type: Lazy.bind.type[_U]

The type of the value that the returned Lazy will produce.

Returns:

The Lazy instance returned by func(value), where value is the result of unwrapping this instance.

Examples

>>> from deluxe.functional import Lazy
>>> def parse_int(s: str) -> Lazy[int]:
...     return Lazy.pure(int(s))
>>> lazy_str = Lazy.pure("42")
>>> lazy_int = lazy_str.bind(parse_int, int)
>>> lazy_int.unwrap()
42
join() Self[source]

Flatten this lazy value by wrapping it again.

Creates a new Lazy instance that will produce the result of unwrapping this instance. This is useful for normalizing lazy values and ensuring a consistent lazy context.

Returns:

A Lazy instance that will produce the same value as calling unwrap() on this instance.

Examples

>>> from deluxe.functional import Lazy
>>> lazy_value = Lazy.pure(42)
>>> lazy_joined = lazy_value.join()
>>> lazy_joined.unwrap()
42
unwrap() _T[source]

Execute the lazy computation and return its result.

This method invokes the wrapped callable and returns its result. The callable is executed each time unwrap() is called; results are not automatically cached.

Returns:

The result of executing the wrapped callable of type _T.

Examples

>>> from deluxe.functional import Lazy
>>> def compute() -> int:
...     print("Computing...")
...     return 42
>>> lazy_value = Lazy(compute, int)
>>> result = lazy_value.unwrap()
Computing...
>>> print(result)
42

Note

lazy_value() is equivalent to lazy_value.unwrap()

class MaybeCallable(value: _T | collections.abc.Callable[[_T], _T])[source]

Extends: Generic[_T]

Monad wrapping up a type or a callable returning this same type.

The MaybeCallable type is designed to represent values that can be either plain values or callables that produce values of the same type. This is particularly useful when defining enumerations where some members are simple values while others are callable (factory) members.

When used as a base class for enumerations, MaybeCallable enables a hybrid pattern where enum members can be either:

  • Plain values: Direct values of the wrapped type.

  • Callable members: Methods decorated with @member that accept arguments and return values of the wrapped type.

Examples

Basic usage with plain values and callables:

from deluxe.functional import MaybeCallable

# Wrapping a plain value
plain = MaybeCallable(42)
print(plain.unwrap())  # 42

# Wrapping a callable
def double(x: int) -> int:
    return x * 2

callable_val = MaybeCallable(double)
print(callable_val(21))  # 42

Usage as an enumeration base class:

from enum import Enum, member
from deluxe.enums import Enum as DocEnum
from deluxe.functional import MaybeCallable

class Key(MaybeCallable[bytes]):
    def __call__(self, *args: bytes) -> bytes:
        return self._callable_(*args)

class KeyStroke(Key[bytes], Enum):
    @staticmethod
    def _join(string: bytes, other: bytes) -> str:
        return string.decode() + other.decode()

    @member
    @staticmethod
    def Ctrl(key: bytes) -> str:
        return KeyStroke._join(b"C-", key)

    @member
    @staticmethod
    def Meta(key: bytes) -> str:
        return KeyStroke._join(b"M-", key)

    Space = b"Space"
    Tab = b"Tab"
    Enter = b"Enter"

# Plain enum members
print(KeyStroke.Space)  # b"Space"
print(KeyStroke.Tab)    # b"Tab"

# Callable enum members
print(KeyStroke.Ctrl(b"h"))  # "C-h"
print(KeyStroke.Meta(b"a"))  # "M-a"

Another example with byte strings:

from deluxe.functional import MaybeCallable
from deluxe.enums import Enum as DocEnum

class BString(MaybeCallable[bytes]):
    @staticmethod
    def format(value: bytes) -> bytes:
        return b"".join((b"#{", value, b"}"))

    def map(self, func):
        return self.pure(func(self.unwrap()))

class Format(BString, DocEnum):
    @member
    @staticmethod
    def str(string: bytes) -> bytes:
        return BString(string)

    @member
    @staticmethod
    def var(string: bytes) -> bytes:
        name = string.decode()
        return getattr(Enum("Format", ((name, string),), type=BString), name)

    active_window_index = b"active_window_index"
    pane_id = b"pane_id"

# Plain enum members
print(Format.active_window_index)  # b"active_window_index"

# Callable enum members
print(Format.var(b"opt"))  # creates a new Format member

Note

When using MaybeCallable as a base for enumerations, the __call__ method should be overridden in the subclass to properly handle callable enum members. The @member decorator from enum is used to mark static methods as callable enum members.

Parameters:
value: _T | collections.abc.Callable[[_T], _T]

Either a plain value or a callable that accepts no arguments and returns a value of the same type.

See also

  • Lazy: A monad for lazy evaluation of computations.

  • Maybe: A monad representing optional values.

  • deluxe.enums.Enum: Enhanced enumeration base class.

classmethod pure(value: _T | collections.abc.Callable[[_T], _T]) Self[source]

Wrap a plain value or callable into the monadic context.

Creates a new MaybeCallable instance containing the given value. This is the primary way to enter the MaybeCallable context from a non-monadic value.

Parameters:
value: _T | collections.abc.Callable[[_T], _T]

A plain value or a callable that returns a value.

Returns:

A new MaybeCallable wrapping the given value.

map(func: collections.abc.Callable[[_T | collections.abc.Callable[[_T], _T]], _T]) Self[source]

Apply a function to the wrapped value (functorial map).

This method transforms the value inside the MaybeCallable context by applying the given function. It preserves the monadic structure, returning a new MaybeCallable containing the transformed value.

Parameters:
func: collections.abc.Callable[[_T | collections.abc.Callable[[_T], _T]], _T]

A callable that receives the wrapped value and returns a transformed value of a (potentially different) type.

Returns:

A new MaybeCallable wrapping the result of func, whose type matches the return type of func.

bind(func: collections.abc.Callable[[_T | collections.abc.Callable[[_T], _T]], Self]) Self[source]

Chain a function that returns a MaybeCallable value.

This method allows for chaining computations that produce MaybeCallable results. It applies the function to the wrapped value, which itself returns a MaybeCallable, and then flattens the result to avoid nested monads.

The bind operation (also known as flatMap or >>= in other languages) is the fundamental operation that gives monads their power for sequencing computations.

Parameters:
func: collections.abc.Callable[[_T | collections.abc.Callable[[_T], _T]], Self]

A callable that receives the wrapped value and returns a MaybeCallable wrapping a value of a (potentially different) type.

Returns:

A new MaybeCallable wrapping the result of func, whose type matches the return type of func, with the nested MaybeCallable structure flattened.

join() Self[source]

Flatten a nested MaybeCallable into a single instance.

This method unwraps one level of monadic structure, which is useful when dealing with nested MaybeCallable contexts. It extracts the value and re-wraps it in a fresh MaybeCallable.

The join operation is related to bind and is defined as: m.join() == m.bind(lambda x: x).

Returns:

A MaybeCallable instance with one level of nesting removed.

unwrap() _T[source]

Extract the plain wrapped value from the monadic context.

This method returns the plain value contained within the monadic structure. Raises an error if the wrapped value is a callable rather than a plain value.

Returns:

The plain value that was wrapped in the MaybeCallable context.

Raises:

TypeError – If the wrapped value is a callable.