Maybe

The Maybe container is used when a series of computations could return None at any point.

Maybe container

Maybe consist of two types: Some and Nothing. We have a convenient method to create different Maybe types based on just a single value:

from returns.maybe import Maybe

Maybe.new(1)
# => Some(1)

Maybe.new(None)
# => Nothing

Usage

It might be very useful for complex operations like the following one:

from dataclasses import dataclass
from typing import Optional

@dataclass
class Address(object):
    street: Optional[str]

@dataclass
class User(object):
    address: Optional[Address]

@dataclass
class Order(object):
    user: Optional[User]

order: Order  # some existing Order instance
street: Maybe[str] = Maybe.new(order.user).map(
    lambda user: user.address,
).map(
    lambda address: address.street,
)
# => `Some('address street info')` if all fields are not None
# => `Nothing` if at least one field is `None`

Optional type

One may ask: “How is that different to the Optional[] type?” That’s a really good question!

Consider the same code to get the street name without Maybe and using raw Optional values:

order: Order  # some existing Order instance
street: Optional[str] = None
if order.user is not None:
    if order.user.address is not None:
        street = order.user.address.street

It looks way uglier and can grow even more uglier and complex when new logic will be introduced.

@maybe decorator

Sometimes we have to deal with functions that dears to return Optional values!

We have to work with it the carefully and write if x is not None: everywhere. Luckily, we have your back! maybe function decorates any other function that returns Optional and converts it to return Maybe instead:

from typing import Optional
from returns.maybe import Maybe, maybe

@maybe
def number(num: int) -> Optional[int]:
    if num > 0:
        return num
    return None

result: Maybe[int] = number(1)
# => Some(1)

API Reference

graph TD; Maybe _Nothing _Some Generic --> Maybe BaseContainer --> Maybe Maybe --> _Nothing Maybe --> _Some
class Maybe(inner_value)[source]

Bases: typing.Generic, returns.primitives.container.BaseContainer

Represents a result of a series of commutation that can return None.

An alternative to using exceptions or constant is None checks. Maybe is an abstract type and should not be instantiated directly. Instead use Some and Nothing.

classmethod new(inner_value)[source]

Creates new instance of Maybe container based on a value.

Return type

Maybe[+_ValueType]

map(function)[source]

Abstract method to compose container with a pure function.

Return type

Maybe[~_NewValueType]

bind(function)[source]

Abstract method to compose container with other container.

Return type

Maybe[~_NewValueType]

fix(function)[source]

Abstract method to compose container with a pure function.

Return type

Maybe[~_NewValueType]

rescue(function)[source]

Abstract method to compose container with other container.

Return type

Maybe[~_NewValueType]

value_or(default_value)[source]

Get value or default value.

Return type

Union[+_ValueType, ~_NewValueType]

unwrap()[source]

Get value or raise exception.

Return type

+_ValueType

failure()[source]

Get failed value or raise exception.

Return type

None

Some(inner_value)[source]

Public unit function of protected _Some type.

Return type

Maybe[+_ValueType]

Nothing = <returns.maybe._Nothing object>

Public unit value of protected _Nothing type.

maybe(function)[source]

Decorator to covert None returning function to Maybe container.

Supports both async and regular functions.

>>> from typing import Optional
>>> @maybe
... def might_be_none(arg: int) -> Optional[int]:
...     if arg == 0:
...         return None
...     return 1 / arg
...
>>> might_be_none(0) == Nothing
True
>>> might_be_none(1) == Some(1.0)
True