2.0 KiB
returns
A library for Python providing implementations of various Monads.
Benefits
Explicit errors
Composition
Asynchronous composition
Drawbacks
Learning curve
Formatting call chains in YAPF
Call chaining formats poorly in YAPF. Consider the following example which performs the following steps:
- Builds a request object
- Wraps the request object in a Future
- Binds the request to the HTTP send method
- Binds the result to a response handler
The code, formatted by YAPF, looks like this:
return FutureResult.from_result(
self.build_request(request)).bind_async(safe_send).bind_result(
self.load_response)
The same code, formatted instead by the Black formatter, looks like this:
return (
FutureResult.from_result(self.build_request(request))
.bind_async(safe_send)
.bind_result(self.load_response)
)
A workaround is to use the pointfree
module from returns
, though this comes
with the additional overhead of understanding and using the point-free
functions.
return flow(
FutureResult.from_result(self.build_request(request)),
pointfree.bind_async(safe_send),
pointfree.bind_result(self.load_response),
)
Opinionated Future IO
Awaiting Future
and FutureResult
returns IO
and IOResult
containers.
While this makes some sense, it's frustrating that the IO
wrapping isn't
opt-in. While Future
and Result
offer the compositional benefits Monads
offer to Python code, IO
as a tool to indicate impure functions/values strikes
me as more of an imposition on development to be added by choice. Having to
unwrap those values is tedious and presents an unpleasant hurdle to interacting
with vanilla Python code.