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 convert 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
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 cannot `.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, just 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_value(
... RequiresContextResult.from_value(1),
... ),
... )(RequiresContext.empty) == Success(1)
See also
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
>>> assert result_to_maybe(Failure(None)) == Nothing
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(Some(1)) == Success(1)
>>> assert maybe_to_result(Nothing) == Failure(None)
>>> assert maybe_to_result(Some(None)) == Failure(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.
It works with Result:
>>> 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'
With IOResult:
>>> 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_ioresult(f1, f2)(IOSuccess(1)) == IO(2)
>>> assert coalesce_ioresult(f1, f2)(IOFailure('a')) == IO('ab')
And with Maybe:
>>> 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'
coalesce_result(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.
It works with Result:
>>> 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'
With IOResult:
>>> 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_ioresult(f1, f2)(IOSuccess(1)) == IO(2)
>>> assert coalesce_ioresult(f1, f2)(IOFailure('a')) == IO('ab')
And with Maybe:
>>> 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'
coalesce_ioresult(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.
It works with Result:
>>> 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'
With IOResult:
>>> 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_ioresult(f1, f2)(IOSuccess(1)) == IO(2)
>>> assert coalesce_ioresult(f1, f2)(IOFailure('a')) == IO('ab')
And with Maybe:
>>> 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'