This module provides a bunch of primitives to work with containers.
It makes composing functions with containers easier. Sometimes using methods on containers is not very helpful. Container methods are difficult to compose with other functions or methods.
Instead we can use functions that produce the same result but have the reverse semantics.
Usually, this means changing something like x.f(y)
to f(x)(y)
.
Why would anyone need these functions when you can use methods? To create pipelines!
from returns.pipeline import pipe
from returns.result import ResultE
def returns_result(arg: int) -> ResultE[int]:
...
def works_with_result(arg: int) -> ResultE[int]:
...
def finish_work(arg: int) -> ResultE[int]:
...
pipe(
returns_result,
works_with_result, # does not compose! Needs a container for input
finish_work, # does not compose either!
)
Without pointfree functions you would probably have to write:
returns_result().bind(works_with_result).bind(notifies_user)
And you need a way to somehow do this in the pipeline syntax. Remember that pipeline syntax helps make composing functions more readable and pythonic. That’s where pointfree functions become really useful.
map_()
is a pointfree alternative to the container method .map()
.
It lifts a function to work from container to container. map_(f)
would return f lifted to work on a container.
In other words, it modifies the function’s signature from:
a -> b
to:
Container[a] -> Container[b]
Doing this lets us compose regular functions and containers.
>>> from returns import pointfree
>>> from returns.maybe import Maybe, Some
>>> def as_int(arg: str) -> int:
... return ord(arg)
>>> container: Maybe[str] = Some('a')
>>> # We now have two ways to compose container and as_int
>>> # 1. Via ``.map()``:
>>> assert container.map(as_int) == Some(97)
>>> # 2. Or via ``map_()``, like above but in the reverse order:
>>> assert pointfree.map_(as_int)(container) == Some(97)
This means we can compose functions in a pipeline.
>>> from returns import pointfree
>>> from returns.pipeline import flow
>>> from returns.maybe import Maybe, Some, Nothing
>>> def index_of_7(arg: str) -> Maybe[int]:
... if '7' in arg:
... return Some(arg.index('7'))
... return Nothing
>>> def double(num: int) -> int:
... return num * 2
>>> assert flow(
... '007',
... index_of_7, # Some(2)
... pointfree.map_(double), # Some(4)
... ) == Some(4)
>>> # Still passes along Nothing
>>> assert flow(
... '006',
... index_of_7, # Nothing
... pointfree.map_(double), # Nothing
... ) == Nothing
Pointfree bind()
is an alternative to the container method .bind()
.
It binds a function that returns a container so that is accepts the same container type as input.
In other words, it modifies the function’s signature from:
a -> Container[b]
to:
Container[a] -> Container[b]
Without bind()
it would be very hard to declaratively compose two entities:
Existing containers
Existing functions that accept a regular value and return a container
We can compose these entities with .bind()
when calling it on a container,
but how can we do it independently?
>>> from returns import pointfree
>>> from returns.maybe import Maybe, Some
>>> def index_of_1(arg: str) -> Maybe[int]:
... if '1' in arg:
... return Some(arg.index('1'))
... return Nothing
>>> container = Some('A1 Steak Sauce')
>>> # We now have two way of composing these entities.
>>> # 1. Via ``.bind``:
>>> assert container.bind(index_of_1) == Some(1)
>>> # 2. Or via the ``bind`` function.
>>> assert pointfree.bind(index_of_1)(container) == Some(1)
>>> # This produces the same result, but in a different order
That’s it!
We also have a long list of other bind_*
functions, like:
bind_io
to bind functions returning IO
container
bind_result
to bind functions returning Result
container
bind_ioresult
to bind functions returning IOResult
container
bind_future
to bind functions returning Future
container
bind_async_future
to bind async functions returning Future
container
bind_future_result
to bind functions returning FutureResult
container
bind_async_future_result
to bind async functions
returning FutureResult
container
bind_context
to bind functions returning RequiresContext
container
bind_context_result
to bind functions
returning RequiresContextResult
container
bind_context_ioresult
to bind functions
returning RequiresContextIOResult
container
bind_async
to bind async functions
returning Future
or FutureResult
bind_awaitable
to bind async non-container functions
Pointfree alt()
is an alternative to the container method .alt()
.
It lifts a function to act on the error contents of a container.
In other words, it modifies the function’s signature from:
a -> b
to:
Container[_, a] -> Container[_, b]
You can think of it like map
, but for the second type of a container.
>>> from returns.io import IOFailure, IOSuccess
>>> from returns import pointfree
>>> def half_as_bad(error_code: int) -> float:
... return error_code / 2
>>> # When acting on a successful state, nothing happens.
>>> assert pointfree.alt(half_as_bad)(IOSuccess(1)) == IOSuccess(1)
>>> # When acting on a failed state, the result changes
>>> assert pointfree.alt(half_as_bad)(IOFailure(4)) == IOFailure(2.0)
>>> # This is equivalent to IOFailure(4).alt(half_as_bad)
>>> assert pointfree.alt(half_as_bad)(IOFailure(4)) == IOFailure(4).alt(half_as_bad)
This inverse syntax lets us easily compose functions in a pipeline
>>> from returns.io import IOFailure, IOSuccess, IOResult
>>> from returns import pointfree
>>> def always_errors(user_input: str) -> IOResult:
... return IOFailure(len(user_input))
>>> def twice_as_bad(exit_code: int) -> int:
... return exit_code * 2
>>> def make_error_message(exit_code: int) -> str:
... return 'Badness level: {0}'.format(exit_code)
>>> assert flow(
... '12345',
... always_errors,
... pointfree.alt(twice_as_bad),
... pointfree.alt(make_error_message)
... ) == IOFailure('Badness level: 10')
Pointfree lash()
function is an alternative
to .lash()
container method.
It allows better composition by lifting a function that returns a container to act on the failed state of a container.
You can think of it like bind
, but for the second type of a container.
>>> from returns import pointfree
>>> from returns.result import Success, Failure, Result
>>> def always_succeeds(arg: str) -> Result[int, str]:
... return Success(1)
>>> failed: Result[int, str] = Failure('a')
>>> # We now have two way of composing these entities.
>>> # 1. Via ``.lash``:
>>> assert failed.lash(always_succeeds) == Success(1)
>>> # 2. Or via ``lash`` function, the same but in the inverse way:
>>> assert pointfree.lash(always_succeeds)(failed) == Success(1)
Pointfree apply
function allows
to use .apply()
container method like a function:
>>> from returns import pointfree
>>> from returns.maybe import Some, Nothing
>>> def wow(arg: int) -> str:
... return chr(arg) + '!'
>>> assert pointfree.apply(Some(wow))(Some(97)) == Some('a!')
>>> assert pointfree.apply(Some(wow))(Some(98)) == Some('b!')
>>> assert pointfree.apply(Some(wow))(Nothing) == Nothing
>>> assert pointfree.apply(Nothing)(Nothing) == Nothing
If you wish to use apply
inside a pipeline
here’s how it might look:
>>> from returns import pointfree
>>> from returns.pipeline import flow
>>> from returns.maybe import Some, Nothing, Maybe
>>> from typing import Callable
>>> def wow(arg: int) -> str:
... return chr(arg) + '!'
>>> def my_response(is_excited: bool) -> Maybe[Callable[[int], str]]:
... if is_excited:
... return Some(wow)
... return Nothing
>>> assert flow(
... Some(97),
... pointfree.apply(my_response(True)),
... ) == Some('a!')
>>> assert flow(
... Nothing,
... pointfree.apply(my_response(False)),
... ) == Nothing
Or with a function as the first parameter:
>>> from returns.pipeline import flow
>>> from returns.curry import curry
>>> from returns.maybe import Some
>>> @curry
... def add_curried(first: int, second: int) -> int:
... return first + second
>>> assert flow(
... Some(add_curried),
... Some(2).apply,
... Some(3).apply,
... ) == Some(5)
Sometimes we need to manipulate the inner Result
of some containers like
IOResult
or FutureResult
. With compose_result
we can do this
kind of manipulation.
>>> from returns import pointfree
>>> from returns.io import IOResult, IOSuccess, IOFailure
>>> from returns.result import Result
>>> def cast_to_str(container: Result[float, int]) -> IOResult[str, int]:
... return IOResult.from_result(container.map(str))
>>> assert pointfree.compose_result(cast_to_str)(IOSuccess(42.0)) == IOSuccess('42.0')
>>> assert pointfree.compose_result(cast_to_str)(IOFailure(1)) == IOFailure(1)
Note
cond
is also the name of a function in the Methods module.
Therefore we encourage to import the modules pointfree
and methods
directly instead of their functions.
Sometimes we need to create SingleFailableN
or DiverseFailableN
containers (e.g. Maybe
, ResultLikeN
) based on a boolean expression,
cond
can help us.
Consider cond
to be a functional if
.
See the example below:
>>> from returns.pipeline import flow
>>> from returns import pointfree
>>> from returns.result import Result, Failure, Success
>>> def returns_boolean(arg: int) -> bool:
... return bool(arg)
>>> assert flow(
... returns_boolean(1),
... pointfree.cond(Result, 'success', 'failure')
... ) == Success('success')
>>> assert flow(
... returns_boolean(0),
... pointfree.cond(Result, 'success', 'failure')
... ) == Failure('failure')
Example using cond
with the Maybe
container:
>>> from returns.pipeline import flow
>>> from returns import pointfree
>>> from returns.maybe import Maybe, Some, Nothing
>>> assert flow(
... returns_boolean(1),
... pointfree.cond(Maybe, 'success')
... ) == Some('success')
>>> assert flow(
... returns_boolean(0),
... pointfree.cond(Maybe, 'success')
... ) == Nothing
Lifts function to be wrapped in a container for better composition.
In other words, it modifies the function’s
signature from:
a -> b
to: Container[a] -> Container[b]
This is how it should be used:
>>> from returns.io import IO
>>> from returns.pointfree import map_
>>> def example(argument: int) -> float:
... return argument / 2
>>> assert map_(example)(IO(1)) == IO(0.5)
Note, that this function works for all containers with .map
method.
See returns.primitives.interfaces.mappable.MappableN
for more info.
See also
function (Callable
[[TypeVar
(_FirstType
)], TypeVar
(_UpdatedType
)]) –
Kinded
[Callable
[[KindN
[TypeVar
(_MappableKind
, bound= MappableN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_MappableKind
, bound= MappableN
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]
Turns function’s input parameter from a regular value to a container.
In other words, it modifies the function
signature from:
a -> Container[b]
to:
Container[a] -> Container[b]
Similar to returns.pointfree.lash()
,
but works for successful containers.
This is how it should be used:
>>> from returns.pointfree import bind
>>> from returns.maybe import Maybe, Some, Nothing
>>> def example(argument: int) -> Maybe[int]:
... return Some(argument + 1)
>>> assert bind(example)(Some(1)) == Some(2)
>>> assert bind(example)(Nothing) == Nothing
Note, that this function works for all containers with .bind
method.
See returns.primitives.interfaces.bindable.BindableN
for more info.
function (Callable
[[TypeVar
(_FirstType
)], KindN
[TypeVar
(_BindableKind
, bound= BindableN
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_BindableKind
, bound= BindableN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_BindableKind
, bound= BindableN
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]
Composes successful container with a function that returns a container.
In other words, it modifies the function’s
signature from:
a -> Result[b, c]
to:
Container[a, c] -> Container[b, c]
>>> from returns.io import IOSuccess
>>> from returns.context import RequiresContextResult
>>> from returns.result import Result, Success
>>> from returns.pointfree import bind_result
>>> def returns_result(arg: int) -> Result[int, str]:
... return Success(arg + 1)
>>> bound = bind_result(returns_result)
>>> assert bound(IOSuccess(1)) == IOSuccess(2)
>>> assert bound(RequiresContextResult.from_value(1))(...) == Success(2)
function (Callable
[[TypeVar
(_FirstType
)], Result
[TypeVar
(_UpdatedType
), TypeVar
(_SecondType
)]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_ResultLikeKind
, bound= ResultLikeN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_ResultLikeKind
, bound= ResultLikeN
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]
Composes successful container with a function that returns a container.
In other words, it modifies the function’s
signature from:
a -> IO[b]
to:
Container[a, c] -> Container[b, c]
>>> from returns.io import IOSuccess, IOFailure
>>> from returns.io import IO
>>> from returns.pointfree import bind_io
>>> def returns_io(arg: int) -> IO[int]:
... return IO(arg + 1)
>>> bound = bind_io(returns_io)
>>> assert bound(IO(1)) == IO(2)
>>> assert bound(IOSuccess(1)) == IOSuccess(2)
>>> assert bound(IOFailure(1)) == IOFailure(1)
function (Callable
[[TypeVar
(_FirstType
, contravariant=True)], IO
[TypeVar
(_UpdatedType
, covariant=True)]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_IOLikeKind
, bound= IOLikeN
), TypeVar
(_FirstType
, contravariant=True), TypeVar
(_SecondType
), TypeVar
(_ThirdType
, contravariant=True)]], KindN
[TypeVar
(_IOLikeKind
, bound= IOLikeN
), TypeVar
(_UpdatedType
, covariant=True), TypeVar
(_SecondType
), TypeVar
(_ThirdType
, contravariant=True)]]]
Composes successful container with a function that returns a container.
In other words, it modifies the function’s
signature from:
a -> IOResult[b, c]
to:
Container[a, c] -> Container[b, c]
>>> from returns.io import IOResult, IOSuccess
>>> from returns.context import RequiresContextIOResult
>>> from returns.pointfree import bind_ioresult
>>> def returns_ioresult(arg: int) -> IOResult[int, str]:
... return IOSuccess(arg + 1)
>>> bound = bind_ioresult(returns_ioresult)
>>> assert bound(IOSuccess(1)) == IOSuccess(2)
>>> assert bound(
... RequiresContextIOResult.from_value(1),
... )(...) == IOSuccess(2)
function (Callable
[[TypeVar
(_FirstType
)], IOResult
[TypeVar
(_UpdatedType
), TypeVar
(_SecondType
)]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_IOResultLikeKind
, bound= IOResultLikeN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_IOResultLikeKind
, bound= IOResultLikeN
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]
Compose a container and sync function returning Future
.
In other words, it modifies the function
signature from:
a -> Future[b]
to:
Container[a] -> Container[b]
Similar to returns.pointfree.lash()
,
but works for successful containers.
This is how it should be used:
>>> import anyio
>>> from returns.pointfree import bind_future
>>> from returns.future import Future
>>> from returns.io import IO
>>> def example(argument: int) -> Future[int]:
... return Future.from_value(argument + 1)
>>> assert anyio.run(
... bind_future(example)(Future.from_value(1)).awaitable,
... ) == IO(2)
Note, that this function works
for all containers with .bind_future
method.
See returns.primitives.interfaces.specific.future.FutureLikeN
for more info.
function (Callable
[[TypeVar
(_FirstType
)], Future
[TypeVar
(_UpdatedType
)]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_FutureKind
, bound= FutureLikeN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_FutureKind
, bound= FutureLikeN
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]
Compose a container and async function returning Future
.
In other words, it modifies the function
signature from:
a -> Awaitable[Future[b]]
to:
Container[a] -> Container[b]
This is how it should be used:
>>> import anyio
>>> from returns.pointfree import bind_async_future
>>> from returns.future import Future
>>> from returns.io import IO
>>> async def example(argument: int) -> Future[int]:
... return Future.from_value(argument + 1)
>>> assert anyio.run(
... bind_async_future(example)(Future.from_value(1)).awaitable,
... ) == IO(2)
Note, that this function works
for all containers with .bind_async_future
method.
See returns.primitives.interfaces.specific.future.FutureLikeN
for more info.
function (Callable
[[TypeVar
(_FirstType
)], Awaitable
[Future
[TypeVar
(_UpdatedType
)]]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_FutureKind
, bound= FutureLikeN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_FutureKind
, bound= FutureLikeN
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]
Compose a container and async function returning FutureResult
.
In other words, it modifies the function
signature from:
a -> FutureResult[b, c]
to:
Container[a, c] -> Container[b, c]
This is how it should be used:
>>> import anyio
>>> from returns.pointfree import bind_future_result
>>> from returns.future import FutureResult
>>> from returns.io import IOSuccess, IOFailure
>>> def example(argument: int) -> FutureResult[int, str]:
... return FutureResult.from_value(argument + 1)
>>> assert anyio.run(
... bind_future_result(example)(
... FutureResult.from_value(1),
... ).awaitable,
... ) == IOSuccess(2)
>>> assert anyio.run(
... bind_future_result(example)(
... FutureResult.from_failure('a'),
... ).awaitable,
... ) == IOFailure('a')
Note, that this function works
for all containers with .bind_async_future
method.
See FutureResultLikeN
for more info.
function (Callable
[[TypeVar
(_FirstType
)], FutureResult
[TypeVar
(_UpdatedType
), TypeVar
(_SecondType
)]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_FutureResultKind
, bound= FutureResultLikeN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_FutureResultKind
, bound= FutureResultLikeN
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]
Compose a container and async function returning FutureResult
.
In other words, it modifies the function
signature from:
a -> Awaitable[FutureResult[b, c]]
to:
Container[a, c] -> Container[b, c]
This is how it should be used:
>>> import anyio
>>> from returns.pointfree import bind_async_future_result
>>> from returns.future import FutureResult
>>> from returns.io import IOSuccess, IOFailure
>>> async def example(argument: int) -> FutureResult[int, str]:
... return FutureResult.from_value(argument + 1)
>>> assert anyio.run(
... bind_async_future_result(example)(
... FutureResult.from_value(1),
... ).awaitable,
... ) == IOSuccess(2)
>>> assert anyio.run(
... bind_async_future_result(example)(
... FutureResult.from_failure('a'),
... ).awaitable,
... ) == IOFailure('a')
Note, that this function works
for all containers with .bind_async_future
method.
See FutureResultLikeN
for more info.
function (Callable
[[TypeVar
(_FirstType
)], Awaitable
[FutureResult
[TypeVar
(_UpdatedType
), TypeVar
(_SecondType
)]]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_FutureResultKind
, bound= FutureResultLikeN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_FutureResultKind
, bound= FutureResultLikeN
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]
Composes successful container with a function that returns a container.
In other words, it modifies the function’s
signature from:
a -> RequresContext[b, c]
to:
Container[a, c] -> Container[b, c]
>>> from returns.pointfree import bind_context2
>>> from returns.context import Reader
>>> def example(argument: int) -> Reader[int, int]:
... return Reader(lambda deps: argument + deps)
>>> assert bind_context2(example)(Reader.from_value(2))(3) == 5
Note, that this function works with only Kind2
containers
with .bind_context
method.
See returns.primitives.interfaces.specific.reader.ReaderLike2
for more info.
function (Callable
[[TypeVar
(_FirstType
)], RequiresContext
[TypeVar
(_UpdatedType
), TypeVar
(_SecondType
)]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_Reader2Kind
, bound= ReaderLike2
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), Any
]], KindN
[TypeVar
(_Reader2Kind
, bound= ReaderLike2
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), Any
]]]
Composes successful container with a function that returns a container.
In other words, it modifies the function’s
signature from: a -> RequresContext[b, c]
to: Container[a, c] -> Container[b, c]
>>> from returns.context import RequiresContext, RequiresContextResult
>>> from returns.result import Success, Failure
>>> from returns.pointfree import bind_context
>>> def function(arg: int) -> RequiresContext[str, int]:
... return RequiresContext(lambda deps: len(deps) + arg)
>>> assert bind_context(function)(
... RequiresContextResult.from_value(2),
... )('abc') == Success(5)
>>> assert bind_context(function)(
... RequiresContextResult.from_failure(0),
... )('abc') == Failure(0)
Note, that this function works with only Kind3
containers
with .bind_context
method.
See returns.primitives.interfaces.specific.reader.ReaderLike3
for more info.
function (Callable
[[TypeVar
(_FirstType
)], RequiresContext
[TypeVar
(_UpdatedType
), TypeVar
(_ThirdType
)]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_Reader3Kind
, bound= ReaderLike3
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_Reader3Kind
, bound= ReaderLike3
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]
Useful alias for bind_context3()
.
function (Callable
[[TypeVar
(_FirstType
)], RequiresContext
[TypeVar
(_UpdatedType
), TypeVar
(_ThirdType
)]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_Reader3Kind
, bound= ReaderLike3
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_Reader3Kind
, bound= ReaderLike3
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]
Modifies the second type argument of a ReaderLike2
.
In other words, it modifies the function’s
signature from:
a -> b
to:
Container[x, a] -> Container[x, b]
>>> from returns.pointfree import modify_env2
>>> from returns.context import RequiresContext
>>> def multiply(arg: int) -> RequiresContext[int, int]:
... return RequiresContext(lambda deps: arg * deps)
>>> assert modify_env2(int)(multiply(3))('4') == 12
Note, that this function works with only Kind2
containers
with .modify_env
method.
See returns.primitives.interfaces.specific.reader.ReaderLike2
for more info.
function (Callable
[[TypeVar
(_UpdatedType
)], TypeVar
(_SecondType
)]) –
Kinded
[Callable
[[KindN
[TypeVar
(_Reader2Kind
, bound= ReaderLike2
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), Any
]], KindN
[TypeVar
(_Reader2Kind
, bound= ReaderLike2
), TypeVar
(_FirstType
), TypeVar
(_UpdatedType
), Any
]]]
Modifies the third type argument of a ReaderLike3
.
In other words, it modifies the function’s
signature from: a -> b
to: Container[x, a] -> Container[x, b]
>>> from returns.pointfree import modify_env
>>> from returns.context import RequiresContextResultE
>>> from returns.result import Success, safe
>>> def divide(arg: int) -> RequiresContextResultE[float, int]:
... return RequiresContextResultE(safe(lambda deps: arg / deps))
>>> assert modify_env(int)(divide(3))('2') == Success(1.5)
>>> assert modify_env(int)(divide(3))('0').failure()
Note, that this function works with only Kind3
containers
with .modify_env
method.
See returns.primitives.interfaces.specific.reader.ReaderLike3
for more info.
function (Callable
[[TypeVar
(_UpdatedType
)], TypeVar
(_ThirdType
)]) –
Kinded
[Callable
[[KindN
[TypeVar
(_Reader3Kind
, bound= ReaderLike3
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_Reader3Kind
, bound= ReaderLike3
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_UpdatedType
)]]]
Useful alias for modify_env3()
.
function (Callable
[[TypeVar
(_UpdatedType
)], TypeVar
(_ThirdType
)]) –
Kinded
[Callable
[[KindN
[TypeVar
(_Reader3Kind
, bound= ReaderLike3
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_Reader3Kind
, bound= ReaderLike3
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_UpdatedType
)]]]
Composes successful container with a function that returns a container.
In other words, it modifies the function’s
signature from:
a -> ReaderResult[b, c, e]
to:
Container[a, c, e] -> Container[b, c, e]
>>> from returns.pointfree import bind_context_result
>>> from returns.context import ReaderIOResult, ReaderResult
>>> from returns.io import IOSuccess, IOFailure
>>> def example(argument: int) -> ReaderResult[int, str, str]:
... return ReaderResult.from_value(argument + 1)
>>> assert bind_context_result(example)(
... ReaderIOResult.from_value(1),
... )(...) == IOSuccess(2)
>>> assert bind_context_result(example)(
... ReaderIOResult.from_failure('a'),
... )(...) == IOFailure('a')
function (Callable
[[TypeVar
(_FirstType
)], RequiresContextResult
[TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_ReaderResultLikeKind
, bound= ReaderResultLikeN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_ReaderResultLikeKind
, bound= ReaderResultLikeN
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]
Lifts function from RequiresContextIOResult
for better composition.
In other words, it modifies the function’s
signature from:
a -> RequiresContextIOResult[env, b, c]
to:
Container[env, a, c]
-> Container[env, b, c]
>>> import anyio
>>> from returns.context import (
... RequiresContextFutureResult,
... RequiresContextIOResult,
... )
>>> from returns.io import IOSuccess, IOFailure
>>> from returns.pointfree import bind_context_ioresult
>>> def function(arg: int) -> RequiresContextIOResult[str, int, str]:
... return RequiresContextIOResult(
... lambda deps: IOSuccess(len(deps) + arg),
... )
>>> assert anyio.run(bind_context_ioresult(function)(
... RequiresContextFutureResult.from_value(2),
... )('abc').awaitable) == IOSuccess(5)
>>> assert anyio.run(bind_context_ioresult(function)(
... RequiresContextFutureResult.from_failure(0),
... )('abc').awaitable) == IOFailure(0)
function (Callable
[[TypeVar
(_FirstType
)], RequiresContextIOResult
[TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_ReaderIOResultLikeKind
, bound= ReaderIOResultLikeN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_ReaderIOResultLikeKind
, bound= ReaderIOResultLikeN
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]
Compose a container and async
function returning a container.
In other words, it modifies the function’s
signature from:
a -> Awaitable[Container[b]]
to:
Container[a] -> Container[b]
This is how it should be used:
>>> import anyio
>>> from returns.future import Future
>>> from returns.io import IO
>>> from returns.pointfree import bind_async
>>> async def coroutine(x: int) -> Future[str]:
... return Future.from_value(str(x + 1))
>>> bound = bind_async(coroutine)(Future.from_value(1))
>>> assert anyio.run(bound.awaitable) == IO('2')
Note, that this function works
for all containers with .bind_async
method.
See returns.primitives.interfaces.specific.future.FutureLikeN
for more info.
function (Callable
[[TypeVar
(_FirstType
)], Awaitable
[KindN
[TypeVar
(_FutureKind
, bound= FutureLikeN
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_FutureKind
, bound= FutureLikeN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_FutureKind
, bound= FutureLikeN
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]
Composes a container a regular async
function.
This function should return plain, non-container value.
In other words, it modifies the function’s
signature from:
a -> Awaitable[b]
to:
Container[a] -> Container[b]
This is how it should be used:
>>> import anyio
>>> from returns.future import Future
>>> from returns.io import IO
>>> from returns.pointfree import bind_awaitable
>>> async def coroutine(x: int) -> int:
... return x + 1
>>> assert anyio.run(
... bind_awaitable(coroutine)(Future.from_value(1)).awaitable,
... ) == IO(2)
Note, that this function works
for all containers with .bind_awaitable
method.
See returns.primitives.interfaces.specific.future.FutureLikeN
for more info.
function (Callable
[[TypeVar
(_FirstType
)], Awaitable
[TypeVar
(_UpdatedType
)]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_FutureKind
, bound= FutureLikeN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_FutureKind
, bound= FutureLikeN
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]
Binds a function returning optional value over a container.
In other words, it modifies the function’s
signature from:
a -> Optional[b]
to:
Container[a] -> Container[b]
>>> from typing import Optional
>>> from returns.pointfree import bind_optional
>>> from returns.maybe import Some, Nothing
>>> def example(argument: int) -> Optional[int]:
... return argument + 1 if argument > 0 else None
>>> assert bind_optional(example)(Some(1)) == Some(2)
>>> assert bind_optional(example)(Some(0)) == Nothing
>>> assert bind_optional(example)(Nothing) == Nothing
Note, that this function works
for all containers with .bind_optional
method.
See returns.primitives.interfaces.specific.maybe._MaybeLikeKind
for more info.
function (Callable
[[TypeVar
(_FirstType
)], Optional
[TypeVar
(_UpdatedType
)]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_MaybeLikeKind
, bound= MaybeLikeN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_MaybeLikeKind
, bound= MaybeLikeN
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]
Composes inner Result
with IOResultLike
returning function.
Can be useful when you need an access to both states of the result.
>>> from returns.io import IOResult, IOSuccess, IOFailure
>>> from returns.pointfree import compose_result
>>> from returns.result import Result
>>> def modify_string(container: Result[str, str]) -> IOResult[str, str]:
... return IOResult.from_result(
... container.map(str.upper).alt(str.lower),
... )
>>> assert compose_result(modify_string)(
... IOSuccess('success')
... ) == IOSuccess('SUCCESS')
>>> assert compose_result(modify_string)(
... IOFailure('FAILURE')
... ) == IOFailure('failure')
function (Callable
[[Result
[TypeVar
(_FirstType
), TypeVar
(_SecondType
)]], KindN
[TypeVar
(_IOResultLikeKind
, bound= IOResultLikeN
), TypeVar
(_NewFirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_IOResultLikeKind
, bound= IOResultLikeN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_IOResultLikeKind
, bound= IOResultLikeN
), TypeVar
(_NewFirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]
Reduce the boilerplate when choosing paths.
Works with SingleFailableN
(e.g. Maybe
)
and DiverseFailableN
(e.g. Result
).
Example using cond
with the Result
container:
>>> from returns.pointfree import cond
>>> from returns.result import Failure, Result, Success
>>> assert cond(Result, 'success', 'failure')(True) == Success('success')
>>> assert cond(Result, 'success', 'failure')(False) == Failure('failure')
Example using cond
with the Maybe
container:
>>> from returns.maybe import Maybe, Some, Nothing
>>> assert cond(Maybe, 10.0)(True) == Some(10.0)
>>> assert cond(Maybe, 10.0)(False) == Nothing
container_type (Union
[Type
[TypeVar
(_SingleFailableKind
, bound= SingleFailableN
)], Type
[TypeVar
(_DiverseFailableKind
, bound= DiverseFailableN
)]]) –
success_value (TypeVar
(_ValueType
)) –
error_value (Optional
[TypeVar
(_ErrorType
)]) –
Lifts function to be wrapped in a container for better composition.
In other words, it modifies the function’s
signature from:
a -> b
to:
Container[a] -> Container[b]
This is how it should be used:
>>> from returns.io import IOFailure, IOSuccess
>>> from returns.pointfree import alt
>>> def example(argument: int) -> float:
... return argument / 2
>>> assert alt(example)(IOSuccess(1)) == IOSuccess(1)
>>> assert alt(example)(IOFailure(4)) == IOFailure(2.0)
Note, that this function works for all containers with .alt
method.
See returns.primitives.interfaces.altable.AltableN
for more info.
function (Callable
[[TypeVar
(_SecondType
)], TypeVar
(_UpdatedType
)]) –
Kinded
[Callable
[[KindN
[TypeVar
(_AltableKind
, bound= AltableN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_AltableKind
, bound= AltableN
), TypeVar
(_FirstType
), TypeVar
(_UpdatedType
), TypeVar
(_ThirdType
)]]]
Turns function’s input parameter from a regular value to a container.
In other words, it modifies the function
signature from:
a -> Container[b]
to:
Container[a] -> Container[b]
Similar to returns.pointfree.bind()
, but works for failed containers.
This is how it should be used:
>>> from returns.pointfree import lash
>>> from returns.result import Success, Failure, Result
>>> def example(argument: int) -> Result[str, int]:
... return Success(argument + 1)
>>> assert lash(example)(Success('a')) == Success('a')
>>> assert lash(example)(Failure(1)) == Success(2)
Note, that this function works for all containers with .lash
method.
See returns.interfaces.lashable.Lashable
for more info.
function (Callable
[[TypeVar
(_SecondType
)], KindN
[TypeVar
(_LashableKind
, bound= LashableN
), TypeVar
(_FirstType
), TypeVar
(_UpdatedType
), TypeVar
(_ThirdType
)]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_LashableKind
, bound= LashableN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_LashableKind
, bound= LashableN
), TypeVar
(_FirstType
), TypeVar
(_UpdatedType
), TypeVar
(_ThirdType
)]]]
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.methods import cond
>>> from returns.pointfree import unify
>>> from returns.result import Result, Success, Failure
>>> def bindable(arg: int) -> Result[int, int]:
... return cond(Result, arg % 2 == 0, arg + 1, arg - 1)
>>> assert unify(bindable)(Success(2)) == Success(3)
>>> assert unify(bindable)(Success(1)) == Failure(0)
>>> assert unify(bindable)(Failure(42)) == Failure(42)
function (Callable
[[TypeVar
(_FirstType
)], KindN
[TypeVar
(_DiverseFailableKind
, bound= DiverseFailableN
), TypeVar
(_NewFirstType
), TypeVar
(_NewSecondType
), TypeVar
(_NewThirdType
)]]) –
Kinded
[Callable
[[KindN
[TypeVar
(_DiverseFailableKind
, bound= DiverseFailableN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_DiverseFailableKind
, bound= DiverseFailableN
), TypeVar
(_NewFirstType
), Union
[TypeVar
(_SecondType
), TypeVar
(_NewSecondType
)], TypeVar
(_NewThirdType
)]]]
Turns container containing a function into a callable.
In other words, it modifies the function
signature from:
Container[a -> b]
to:
Container[a] -> Container[b]
This is how it should be used:
>>> from returns.pointfree import apply
>>> from returns.maybe import Some, Nothing
>>> def example(argument: int) -> int:
... return argument + 1
>>> assert apply(Some(example))(Some(1)) == Some(2)
>>> assert apply(Some(example))(Nothing) == Nothing
>>> assert apply(Nothing)(Some(1)) == Nothing
>>> assert apply(Nothing)(Nothing) == Nothing
Note, that this function works for all containers with .apply
method.
See returns.interfaces.applicative.ApplicativeN
for more info.
container (KindN
[TypeVar
(_ApplicativeKind
, bound= ApplicativeN
), Callable
[[TypeVar
(_FirstType
)], TypeVar
(_UpdatedType
)], TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]) –
Kinded
[Callable
[[KindN
[TypeVar
(_ApplicativeKind
, bound= ApplicativeN
), TypeVar
(_FirstType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]], KindN
[TypeVar
(_ApplicativeKind
, bound= ApplicativeN
), TypeVar
(_UpdatedType
), TypeVar
(_SecondType
), TypeVar
(_ThirdType
)]]]