Result

Make sure to get familiar with Railway oriented programming.

Result is obviously a result of some series of computations. It might succeed with some resulting value. Or it might return an error with some extra details.

Result consist of two types: Success and Failure. Success represents successful operation result and Failure indicates that something has failed.

from returns.result import Result, Success, Failure

def find_user(user_id: int) -> Result['User', str]:
    user = User.objects.filter(id=user_id)
    if user.exists():
        return Success(user[0])
    return Failure('User was not found')

user_search_result = find_user(1)
# => Success(User{id: 1, ...})

user_search_result = find_user(0)  # id 0 does not exist!
# => Failure('User was not found')

When is it useful? When you do not want to use exceptions to break your execution scope. Or when you do not want to use None to represent empty values, since it will raise TypeError somewhere and other None exception-friends.

Composition

Make sure to check out how to compose container with flow or pipe! Read more about them if you want to compose your containers easily.

Aliases

There are several useful alises for Result type with some common values:

  • returns.result.ResultE is an alias for Result[... Exception], just use it when you want to work with Result containers that use exceptions as error type. It is named ResultE because it is ResultException and ResultError at the same time.

Decorators

Limitations

Typing will only work correctly if our mypy plugin is used. This happens due to mypy issue.

safe

safe is used to convert regular functions that can throw exceptions to functions that return Result type.

Supports both async and regular functions.

>>> from returns.result import safe

>>> @safe  # Will convert type to: Callable[[int], Result[float, Exception]]
... def divide(number: int) -> float:
...     return number / number

>>> str(divide(1))
'<Success: 1.0>'

>>> str(divide(0))
'<Failure: division by zero>'

FAQ

How to create unit objects?

Use Success or Failure. Alternatively returns.result.Result.from_value() or returns.result.Result.from_failure().

It might be a good idea to use unit functions together with the explicit annotation. Python’s type system does not allow us to do much, so this is required:

>>> from returns.result import Result, Success

>>> def callback(arg: int) -> Result[float, int]:
...     return Success(float(arg))

>>> first: Result[int, int] = Success(1)
>>> str(first.bind(callback))
'<Success: 1.0>'

Otherwise first will have Result[int, Any] type. Which is okay in some situations.

What is the difference between Success and _Success?

You might wonder why Success is a function and _Success is internal type, that should not be used directly.

Well, that’s a complicated question. Let’s find out.

Let’s begin with haskell definition:

Prelude> :t Left 1
Left 1 :: Num a => Either a b
Prelude> :t Right 1
Right 1 :: Num b => Either a b

As you can see: Left (Failure) and Right (Success) are type constructors: that return Either a b (Result[b, a]) value.

It means, that there’s no single type Left a that makes sense without Right b. Only their duality makes sense to us.

In python we have functions that can be used as type constructors. That’s why we use Success and Failure functions. But, when we need to implement the behaviour of these types - we use real classes inside. That’s how we know what to do in each particular case. In haskell we use pattern matching for this.

That’s why we have public type constructor functions: Success and Failure and internal implementation.

How to compose error types?

You might want to sometimes use .unify instead of .bind to compose error types together. While .bind enforces error type to stay the same, .unify is designed to return a Union of a revious error type and a new one.

It gives an extra flexibility, but also provokes more thinking and can be problematic in some cases.

Like so:

>>> from returns.result import Result, Success

>>> def div(number: int) -> Result[float, ZeroDivisionError]:
...     return Success(1 / number)

>>> container: Result[int, ValueError] = Success(1)
>>> str(container.unify(div))
'<Success: 1.0>'

>>> # => Revealed type is:
>>> # Result[float, Union[ValueError, ZeroDivisionError]]

So, that’s a way to go, if you need this composition.

API Reference

graph TD; Result _Success _Failure BaseContainer --> Result Generic --> Result Result --> _Failure Result --> _Success
class Result(inner_value)[source]

Bases: returns.primitives.container.BaseContainer, typing.Generic

Base class for _Failure and _Success.

Result does not have a public constructor. Use Success() and Failure() to construct the needed values.

success_type

Success type that is used to represent the successful computation.

Parameters

inner_value (+_ValueType) –

alias of _Success

failure_type

Failure type that is used to represent the failed computation.

Parameters

inner_value (+_ErrorType) –

alias of _Failure

map(function)[source]

Composes successful container with a pure function.

>>> from returns.result import Failure, Success

>>> def mappable(string: str) -> str:
...      return string + 'b'

>>> assert Success('a').map(mappable) == Success('ab')
>>> assert Failure('a').map(mappable) == Failure('a')
Parameters

function (Callable[[+_ValueType], ~_NewValueType]) –

Return type

Result[~_NewValueType, +_ErrorType]

apply(container)[source]

Calls a wrapped function in a container on this container.

>>> from returns.result import Failure, Success

>>> def appliable(string: str) -> str:
...      return string + 'b'

>>> assert Success('a').apply(Success(appliable)) == Success('ab')
>>> assert Failure('a').apply(Success(appliable)) == Failure('a')

>>> with_failure = Success('a').apply(Failure(appliable))
>>> assert isinstance(with_failure, Result.failure_type)
Parameters

container (Result[Callable[[+_ValueType], ~_NewValueType], +_ErrorType]) –

Return type

Result[~_NewValueType, +_ErrorType]

bind(function)[source]

Composes successful container with a function that returns a container.

>>> from returns.result import Result, Success, Failure

>>> def bindable(arg: str) -> Result[str, str]:
...      if len(arg) > 1:
...          return Success(arg + 'b')
...      return Failure(arg + 'c')

>>> assert Success('aa').bind(bindable) == Success('aab')
>>> assert Success('a').bind(bindable) == Failure('ac')
>>> assert Failure('a').bind(bindable) == Failure('a')
Parameters

function (Callable[[+_ValueType], Result[~_NewValueType, +_ErrorType]]) –

Return type

Result[~_NewValueType, +_ErrorType]

unify(function)[source]

Composes successful container with a function that returns a container.

Similar to bind() but has different type. It returns Result[ValueType, Union[OldErrorType, NewErrorType]] instead of Result[ValueType, OldErrorType].

So, it can be more useful in some situations. Probably with specific exceptions.

>>> from returns.result import Result, Success, Failure

>>> def bindable(arg: str) -> Result[str, str]:
...      if len(arg) > 1:
...          return Success(arg + 'b')
...      return Failure(arg + 'c')

>>> assert Success('aa').unify(bindable) == Success('aab')
>>> assert Success('a').unify(bindable) == Failure('ac')
>>> assert Failure('a').unify(bindable) == Failure('a')
Parameters

function (Callable[[+_ValueType], Result[~_NewValueType, ~_NewErrorType]]) –

Return type

Result[~_NewValueType, Union[+_ErrorType, ~_NewErrorType]]

fix(function)[source]

Composes failed container with a pure function to fix the failure.

>>> from returns.result import Failure, Success

>>> def fixable(arg: str) -> str:
...      return 'ab'

>>> assert Success('a').fix(fixable) == Success('a')
>>> assert Failure('a').fix(fixable) == Success('ab')
Parameters

function (Callable[[+_ErrorType], ~_NewValueType]) –

Return type

Result[~_NewValueType, +_ErrorType]

alt(function)[source]

Composes failed container with a pure function to modify failure.

>>> from returns.result import Result, Failure, Success

>>> def altable(arg: str) -> Result[str, str]:
...      return arg + 'b'

>>> assert Success('a').alt(altable) == Success('a')
>>> assert Failure('a').alt(altable) == Failure('ab')
Parameters

function (Callable[[+_ErrorType], ~_NewErrorType]) –

Return type

Result[+_ValueType, ~_NewErrorType]

rescue(function)[source]

Composes failed container with a function that returns a container.

>>> from returns.result import Result, Success, Failure

>>> def rescuable(arg: str) -> Result[str, str]:
...      if len(arg) > 1:
...          return Success(arg + 'b')
...      return Failure(arg + 'c')

>>> assert Success('a').rescue(rescuable) == Success('a')
>>> assert Failure('a').rescue(rescuable) == Failure('ac')
>>> assert Failure('aa').rescue(rescuable) == Success('aab')
Parameters

function (Callable[[+_ErrorType], Result[+_ValueType, ~_NewErrorType]]) –

Return type

Result[+_ValueType, ~_NewErrorType]

value_or(default_value)[source]

Get value or default value.

>>> from returns.result import Failure, Success
>>> assert Success(1).value_or(2) == 1
>>> assert Failure(1).value_or(2) == 2
Parameters

default_value (~_NewValueType) –

Return type

Union[+_ValueType, ~_NewValueType]

unwrap()[source]

Get value or raise exception.

>>> from returns.result import Failure, Success
>>> assert Success(1).unwrap() == 1

>>> Failure(1).unwrap()
Traceback (most recent call last):
  ...
returns.primitives.exceptions.UnwrapFailedError
Return type

+_ValueType

failure()[source]

Get failed value or raise exception.

>>> from returns.result import Failure, Success
>>> assert Failure(1).failure() == 1

>>> Success(1).failure()
Traceback (most recent call last):
  ...
returns.primitives.exceptions.UnwrapFailedError
Return type

+_ErrorType

classmethod from_value(inner_value)[source]

One more value to create success unit values.

This is a part of returns.primitives.interfaces.Unitable. It is useful as a united way to create a new value from any container.

>>> from returns.result import Result, Success
>>> assert Result.from_value(1) == Success(1)

You can use this method or Success(), choose the most convenient for you.

Parameters

inner_value (~_NewValueType) –

Return type

Result[~_NewValueType, Any]

classmethod from_failure(inner_value)[source]

One more value to create failure unit values.

This is a part of returns.primitives.interfaces.Unitable. It is useful as a united way to create a new value from any container.

>>> from returns.result import Result, Failure
>>> assert Result.from_failure(1) == Failure(1)

You can use this method or Failure(), choose the most convenient for you.

Parameters

inner_value (~_NewErrorType) –

Return type

Result[Any, ~_NewErrorType]

classmethod from_iterable(inner_value)[source]

Transforms an iterable of Result containers into a single container.

>>> from returns.result import Result, Success, Failure

>>> assert Result.from_iterable([
...    Success(1),
...    Success(2),
... ]) == Success((1, 2))

>>> assert Result.from_iterable([
...     Success(1),
...     Failure('a'),
... ]) == Failure('a')

>>> assert Result.from_iterable([
...     Failure('a'),
...     Success(1),
... ]) == Failure('a')
Parameters

inner_value (Iterable[Result[+_ValueType, +_ErrorType]]) –

Return type

Result[Sequence[+_ValueType], +_ErrorType]

Success(inner_value)[source]

Public unit function of protected _Success type.

>>> from returns.result import Success
>>> str(Success(1))
'<Success: 1>'
Parameters

inner_value (~_NewValueType) –

Return type

Result[~_NewValueType, Any]

Failure(inner_value)[source]

Public unit function of protected _Failure type.

>>> from returns.result import Failure
>>> str(Failure(1))
'<Failure: 1>'
Parameters

inner_value (~_NewErrorType) –

Return type

Result[Any, ~_NewErrorType]

ResultE = returns.result.Result[+_ValueType, Exception]

Alias for a popular case when Result has Exception as error type.

safe(function)[source]

Decorator to convert exception-throwing function to Result container.

Should be used with care, since it only catches Exception subclasses. It does not catch BaseException subclasses.

If you need to mark async function as safe, use returns.future.future_safe() instead. This decorator only works with sync functions. Example:

>>> from returns.result import Result, Success, safe

>>> @safe
... def might_raise(arg: int) -> float:
...     return 1 / arg
...

>>> assert might_raise(1) == Success(1.0)
>>> assert isinstance(might_raise(0), Result.failure_type)

Similar to returns.io.impure_safe() and returns.future.future_safe() decorators.

Requires our mypy plugin.

Parameters

function (Callable[…, +_ValueType]) –

Return type

Callable[…, Result[+_ValueType, Exception]]

Maybe IO