The Maybe
container is used when a series of computations
could return None
at any point.
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
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`
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.
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)
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
.
new
(inner_value)[source]¶Creates new instance of Maybe container based on a value.
Maybe
[+_ValueType]
map
(function)[source]¶Abstract method to compose container with a pure function.
Maybe
[~_NewValueType]
bind
(function)[source]¶Abstract method to compose container with other container.
Maybe
[~_NewValueType]
fix
(function)[source]¶Abstract method to compose container with a pure function.
Maybe
[~_NewValueType]
rescue
(function)[source]¶Abstract method to compose container with other container.
Maybe
[~_NewValueType]
Some
(inner_value)[source]¶Public unit function of protected _Some 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