Closed
Description
There should be a way to write point-free async
functions. What we need is some implementation of fmap
and bind
/join
, treating either an awaitable itself or an async function returning an awaitable as the underlying monad. For example:
def and_then[**T, U, V](
async_func: async (**T) -> U,
normal_func: U -> V,
) -> async (**T) -> V =
"""Monadic fmap for async functions."""
async def (*args, **kwargs) -> normal_func(await async_func(*args, **kwargs))
def then_await[**T, U](
async_async_func: async (**T) -> Awaitable[U],
) -> async (**T) -> U =
"""Monadic join for async functions."""
async def (*args, **kwargs) -> await (await async_async_func(*args, **kwargs))
def and_then_await[**T, U, V](
async_f: async (**T) -> U,
async_g: async U -> V,
) -> async (**T) -> V =
"""Monadic bind for async functions."""
async_f `and_then` async_g `then_await`
which would let you do stuff like
my_async_func: async int -> int
new_async_func: async str -> int = (
int
..> my_async_func
`and_then`
(.*2)
`and_then_await`
my_async_func
)