Maybe#
A container that optionally holds a value.
A Maybe has two possible states, Just or Nothing. Just means a value is present, and Nothing means the value is absent.
The reason that we don't use Some-None or Nil nomencalture is to avoid confusion with the built-in None.
This module also provides a some constructor, which converts an Optional[T] value to a Maybe[T] value.
Rationale#
Python has a built-in None object that represents the absence of a value,
and a corresponding type hint Optional[T].
However, an Optional[T] is semantically different from a Maybe[T] object.
An Optional[T] is a union of T and None, not a single object.
To use a union, you must explicitly check its type before every use.
# Usage 1
if optional is None:
...
else:
do_something(optional)
# Usage 2
do_something(optional) if optional is not None else ...
# Usage 3
optional is not None and do_something(optional)
On the other hand, a Maybe[T] object represents the absence of a value as a state.
Operations defined on Maybe[T] objects behave differently depending on the state of the object, but they are always available regardless of the state.
j: Maybe[int] = just(42)
j.map(do_something) #(1)!
n: Maybe[int] = nothing()
n.map(do_something) #(2)!
do_somethingis called becausejisJust.do_somethingis not called becausenisNothing.
Warning
Notice that None is not equal to Nothing.
Use Maybe.is_nothing() to check if a Maybe object is Nothing.
Implementation#
Maybe implements the following interfaces:
| Interface | Methods |
|---|---|
Functor |
map |
Applicative |
pure, apply |
Monad |
bind(and_then) |
The Maybe class is a generic class that holds a value of type T inside _val field.
A boolean flag _has_value is used to indicate whether the value is present or absent.
If _has_value is False, reading from _val is an undefined behavior.
Maybe and its methods do not support inherit-based subclassing.
Maybe's APIs are based on the Rust Option,
and the comparison table is provided below.
Reference Option |
Counterpart |
|---|---|
and |
and_ |
and_then |
|
as_deref |
|
as_deref_mut |
|
as_mut |
|
as_mut_slice |
|
as_pin_mut |
|
as_pin_ref |
|
as_ref |
|
as_slice |
|
cloned |
|
copied |
|
expect |
|
filter |
|
flatten |
|
get_or_insert |
|
get_or_insert_default |
|
get_or_insert_with |
|
insert |
|
inspect |
tap |
is_none |
is_nothing |
is_some |
is_just |
is_some_and |
is_just_and |
iter |
|
iter_mut |
|
map |
|
map_or |
|
map_or_else |
|
ok_or |
|
ok_or_else |
|
or |
or_ |
or_else |
|
replace |
|
take |
|
take_if |
|
transpose |
|
unwrap |
|
unwrap_or |
|
unwrap_or_default |
|
unwrap_or_else |
|
unwrap_unchecked |
|
unzip |
|
xor |
|
zip |
|
zip_with |
just
#
Constructs a Just value.
Warning
Calling just(None) will return a Just(None) value, not a Nothing value.
If you want to map None to Nothing, use some instead.
nothing
#
some
#
Maybe
#
A container that optionally holds a value. See module-level documentation for more information.
__eq__(other)
#
If both values are Just, compare the inner values. Otherwise, return True if both are Nothing.
Warning
Notice that None is not equal to Nothing.
__len__()
#
Return 1 if the value is Just, otherwise 0.
and_(other)
#
If the value is Just, return a shallow copy of the other Maybe. Otherwise, return a new Nothing of type Maybe[U].
and_then(f)
#
apply(f)
#
Implementation of Applicative.apply.
Applies the callable wrapped within a Maybe to the inner value, if both are Just.
bind(f)
#
Implementation of Monad.bind.
Alias of and_then.
duplicate(m)
classmethod
#
Create a shallow copy of a Maybe value.
expect(message)
#
Unwrap the inner value, if any. Otherwise, raise a ValueError with a custom message.
Raises:
| Type | Description |
|---|---|
ValueError
|
If the value is a |
filter(p)
#
flatten()
#
Flatten a nested Maybe value for one level.
Unlike Option::flatten, this method does not require the inner value to be a Maybe.
If it's not a nested Maybe, this is a no-op.
get_or_insert(val)
#
get_or_insert_with(d)
#
insert(val)
#
Insert a value and returns it.
is_just()
#
Check if the value is a Just.
is_just_and(p)
#
Check if the value is a Just and satisfies the predicate.
is_nothing()
#
Check if the value is a Nothing.
Note
A Just(Nothing) value of type Maybe[Maybe[T]] or a Just(None) value of type Maybe[Optional[T]] are not Nothings.
just(val)
classmethod
#
Construct a Just value.
Warning
Prefer using just instead, unless in performance-critical code.
map(f)
#
Apply a function that maps the inner value to a new value, if any. Otherwise, return Nothing.
See Option::map.
map_or(default, f)
#
Map the inner value using a function, or use the default value if absent.
Tip
If the default value is an expensive expression, use map_or_else instead.
```python j = justint n = nothingint
assert j.map_or(0, lambda x: x + 1) == 43 assert n.map_or(0, lambda x: x + 1) == 0 ```z
map_or_else(d, f)
#
nothing()
classmethod
#
Construct a Nothing value.
Warning
Prefer using Nothing instead, unless in performance-critical code.
or_(other)
#
If the value is Just, return a shallow copy of itself. Otherwise, return the other Maybe's shallow copy.
Notice that the right-hand side should be a Maybe object with the same inner type,
although this is not enforced at runtime.
And also this method does not short-circuit.
or_else(f)
#
Return a shallow copy of the Maybe if it contains a value, otherwise call a function to get a result.
pure(x)
classmethod
#
Implementation of Applicative.pure, which is equivalent to Maybe.just.
replace(val)
#
Replace the inner value with a new value, returning the old value.
After replacement, self will always have a value.
some(val)
classmethod
#
Convert an Optional[T] value to a Maybe value.
Warning
Prefer using some function instead, unless in performance-critical code.
take()
#
take_if(p)
#
Take the inner value out if it satisfies the predicate, and leave no value in place. Otherwise, take out nothing.
tap(f)
#
Call a function with the inner value, if any, and return the Maybe itself.
Unlike Option::inspect, this method does not require the function to return None.
unwrap()
#
unwrap_or(default)
#
unwrap_or_else(f)
#
Unwrap the inner value, or return a value computed by a function if absent.
unwrap_unchecked()
#
Return the inner value without checking if it is a Just or Nothing.
xor(other)
#
zip(*others)
#
Combine multiple Maybe values into a single Maybe value containing a tuple of them.
If all values are Just, return a Just value with a tuple of inner values.
Otherwise, return a Nothing.
Calling this method with no arguments is equivalent to calling map with a tuple constructor.
Typing
The type checker only supports zipping up to 5-tuple.