Converters

We have several helpers to convert containers from one type to another and back again.

Maybe and Result

We have two converters to work with Result <-> Maybe tranformations:

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.

flatten

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)

swap

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)

coalesce

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

squash

squash_io

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.

squash_context

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]]

API Reference

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)
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
Return type

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)
Return type

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.

Note::

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'