We have several helpers to convert containers from one type to another and back again.
We have two converters to work with Result <-> Maybe
tranformations:
maybe_to_result()
that converts Maybe
to Result
result_to_maybe()
that converts Result
to Maybe
That’s how they work:
>>> from returns.converters import maybe_to_result, result_to_maybe
>>> from returns.maybe import Maybe, Some
>>> from returns.result import Result, Success
>>> result: Result[int, Exception] = Success(1)
>>> maybe: Maybe[int] = result_to_maybe(result)
>>> assert maybe == Some(1)
>>> new_result: Result[int, None] = maybe_to_result(maybe)
>>> assert new_result == Success(1)
Take a note, that type changes.
Also, take a note that Success(None)
will be converted to Nothing
.
You can also use
flatten
to merge nested containers together:
>>> from returns.converters import flatten
>>> from returns.maybe import Some
>>> from returns.result import Success
>>> from returns.io import IO
>>> assert flatten(IO(IO(1))) == IO(1)
>>> assert flatten(Some(Some(1))) == Some(1)
>>> assert flatten(Success(Success(1))) == Success(1)
You can use swap
to swap value and error types in Result
and IOResult
containers.
In other words: swap(Result[a, b]) == Result[b, a]
.
This is useful for error handling and composition.
Here’s an example of how swap
works:
>>> from returns.converters import swap
>>> from returns.io import IOSuccess, IOFailure
>>> from returns.result import Success, Failure
>>> assert swap(IOSuccess(1)) == IOFailure(1)
>>> assert swap(Failure(2)) == Success(2)
You can use swap
twice to get the same object back!
>>> from returns.converters import swap
>>> from returns.io import IOSuccess
>>> assert swap(swap(IOSuccess(1))) == IOSuccess(1)
You can use
coalesce_result
,
coalesce_ioresult
,
and coalesce_maybe
converters to covert containers to a regular value.
These functions accept two functions: one for successful case, one for failing case.
>>> from returns.converters import coalesce_result
>>> from returns.result import Success, Failure
>>> def handle_success(state: int) -> float:
... return state / 2
...
>>> def handle_failure(state: str) -> float:
... return 0.0
...
>>> assert coalesce_result(handle_success, handle_failure)(Success(1)) == 0.5
>>> assert coalesce_result(handle_success, handle_failure)(Failure(1)) == 0.0
returns.converters.squash_io()
function
allows to squash several IO
containers together.
That’s how it works:
>>> from returns.io import IO
>>> from returns.converters import squash_io
>>> assert squash_io(IO('first'), IO('second')) == IO(('first', 'second'))
>>> # => revealed type of this instance is `IO[Tuple[str, str]]`
It might be helpful if you want
to work with mutliple IO
instances at the same time.
This approach saves you you from multiple nested IO.map
calls.
You can work with tuples instead like so:
>>> plus = squash_io(IO(1), IO('a')).map(lambda args: args[0] + len(args[1]))
>>> assert plus == IO(2)
We support up to 9 typed parameters to this function.
returns.converters.squash_context()
is similar to squash_io
,
but works with RequiresContext
container.
>>> from returns.context import RequiresContext
>>> from returns.converters import squash_context
>>> assert squash_context(
... RequiresContext.from_value(1),
... RequiresContext.from_value('a'),
... )(...) == RequiresContext.from_value((1, 'a'))(...)
>>> # revealed type is: RequiresContext[Any, Tuple[int, str]]
swap
(container)¶Swaps value and error types in a container.
Why? Because we have a lot of .bind
related helpers
and none .rescue
related helpers.
So, you can swap
a container to handle errors in a simple way,
and then swap it back to continue normal execution.
>>> from returns.converters import swap
>>> from returns.io import IOResult, IOSuccess, IOFailure
>>> container: IOResult[int, str] = IOSuccess(1)
>>> swapped: IOResult[str, int] = swap(container)
>>> assert swapped == IOFailure(1)
>>> container: IOResult[int, str] = IOFailure('error')
>>> assert swap(container) == IOSuccess('error')
And here’s how you can handle errors easily:
>>> from returns.converters import swap
>>> from returns.io import IOResult, IOSuccess
>>> from returns.result import Result, Success
>>> def function(error: str) -> Result[str, int]:
... return Success('Very bad error: ' + error)
...
>>> container: IOResult[int, str] = IOFailure('boom')
>>> # You can `.rescue_result`, but you can `.bind_result` instead!
>>> assert swap(
... swap(container).bind_result(function),
... ) == IOFailure('Very bad error: boom')
This converter supports only containers
that have .success_type
property.
Basically Result
and IOResult
.
flatten
(container)¶Joins two nested containers together.
Please, note that it will not join
two Failure
for Result
case
or two Nothing
for Maybe
case together.
>>> from returns.converters import flatten
>>> from returns.maybe import Some
>>> from returns.result import Failure, Success
>>> from returns.io import IO, IOSuccess, IOFailure
>>> from returns.context import RequiresContext, RequiresContextResult
>>> assert flatten(IO(IO(1))) == IO(1)
>>> assert flatten(Some(Some(1))) == Some(1)
>>> assert flatten(Success(Success(1))) == Success(1)
>>> assert flatten(Failure(Failure(1))) == Failure(Failure(1))
>>> assert flatten(IOSuccess(IOSuccess(1))) == IOSuccess(1)
>>> assert flatten(IOFailure(IOFailure(1))) == IOFailure(IOFailure(1))
>>> assert flatten(
... RequiresContext.from_value(RequiresContext.from_value(1)),
... )(RequiresContext.empty) == 1
>>> assert flatten(
... RequiresContextResult.from_success(
... RequiresContextResult.from_success(1),
... ),
... )(RequiresContext.empty) == Success(1)
See also
squash_io
(*args)¶Unwraps IO
values, merges them into tuple, and wraps back.
>>> from returns.io import IO
>>> from returns.converters import squash_io
>>> assert squash_io(IO('a'), IO('b')) == IO(('a', 'b'))
Why this only exists for IO
and RequiresContext
?
Because these types represent real values, that do not possibly fail.
How would you, for example, squash two Result
values?
Success(1)
and Failure(2)
would not give you a tuple when squashed.
squash_context
(*args)¶Unwraps RequiresContext
values, merges them into tuple, and wraps back.
>>> from returns.context import RequiresContext
>>> from returns.converters import squash_context
>>> assert squash_context(
... RequiresContext.from_value(1),
... RequiresContext.from_value('a'),
... RequiresContext.from_value(True),
... )(...) == RequiresContext.from_value((1, 'a', True))(...)
See returns.converters.squash_io()
for more docs.
result_to_maybe
(result_container)[source]¶Converts Result
container to Maybe
container.
>>> from returns.maybe import Some, Nothing
>>> from returns.result import Failure, Success
>>> assert result_to_maybe(Success(1)) == Some(1)
>>> assert result_to_maybe(Failure(1)) == Nothing
>>> assert result_to_maybe(Success(None)) == Nothing
Maybe
[~_ValueType]
maybe_to_result
(maybe_container)[source]¶Converts Maybe
container to Result
container.
>>> from returns.maybe import Some, Nothing
>>> from returns.result import Failure, Success
>>> assert maybe_to_result(Nothing) == Failure(None)
>>> assert maybe_to_result(Some(1)) == Success(1)
>>> assert maybe_to_result(Some(None)) == Failure(None)
Result
[~_ValueType, None
]
coalesce_maybe
(success_handler, failure_handler)¶Accepts two functions that handle different cases of containers.
First one handles successful containers like Some
and Success
,
and second one for failed containers like Nothing
and Failure
.
This function is useful when you need to coalesce two possible container states into one type.
IOResult
only coalesce to IO
values.
It is impossible to unwrap IO
here.
>>> from returns.converters import coalesce_result
>>> from returns.result import Success, Failure
>>> f1 = lambda x: x + 1
>>> f2 = lambda y: y + 'b'
>>> assert coalesce_result(f1, f2)(Success(1)) == 2
>>> assert coalesce_result(f1, f2)(Failure('a')) == 'ab'
>>> from returns.converters import coalesce_ioresult
>>> from returns.io import IO, IOSuccess, IOFailure
>>> f1 = lambda x: x.map(lambda state: state + 1)
>>> f2 = lambda y: y.map(lambda state: state + 'b')
>>> assert coalesce_result(f1, f2)(IOSuccess(1)) == IO(2)
>>> assert coalesce_result(f1, f2)(IOFailure('a')) == IO('ab')
>>> from returns.converters import coalesce_maybe
>>> from returns.maybe import Some, Nothing
>>> f1 = lambda x: x + 1
>>> f2 = lambda _: 'a'
>>> assert coalesce_maybe(f1, f2)(Some(1)) == 2
>>> assert coalesce_maybe(f1, f2)(Nothing) == 'a'