Long before I found Returns, I implemented my own Result monad from scratch. It was a lot of fun, and right now it coexists with Returns as the library it's a part of is being incrementally deprecated. At some point, I decided it would be nice if I could do things like this:
result = some_function() # Result[S, F]
if result:
reveal_type(result) # Success[S]
else:
reveal_type(result) # Failure[F]
It's worked great. I have my own analogue to is_successful, but with __bool__ I don't even have to import it. Also, it actually works better than my functions: my analogue is a pair of TypeGuard functions (TypeIs didn't exist yet), so even after narrowing the container type in the first if, the else would have no type information about the container. Cf., __bool__(self) -> Literal[False] and __bool__(self) -> Literal[True] make type narrowing work perfectly, and it feels very pythonic, imo.
As I update more and more code to use Returns, instead, I find this to be the one thing about my library that I actually miss. There are a lot of cases where I could reach for match for something as ergonomic, but most of the time I'm only interested in Success vs. Failure; match is overkill if I don't need to peak at the contained value.
The one drawback I anticipate to adding this feature would be the possibility of breaking any code that's relying on the default object.__bool__ behavior to differentiate a Failure from eg. a None... but hopefully, anybody using this library would have their Optionals wrapped in a Maybe already?
Long before I found Returns, I implemented my own Result monad from scratch. It was a lot of fun, and right now it coexists with Returns as the library it's a part of is being incrementally deprecated. At some point, I decided it would be nice if I could do things like this:
It's worked great. I have my own analogue to
is_successful, but with__bool__I don't even have to import it. Also, it actually works better than my functions: my analogue is a pair ofTypeGuardfunctions (TypeIsdidn't exist yet), so even after narrowing the container type in the firstif, theelsewould have no type information about the container. Cf.,__bool__(self) -> Literal[False]and__bool__(self) -> Literal[True]make type narrowing work perfectly, and it feels very pythonic, imo.As I update more and more code to use Returns, instead, I find this to be the one thing about my library that I actually miss. There are a lot of cases where I could reach for
matchfor something as ergonomic, but most of the time I'm only interested in Success vs. Failure;matchis overkill if I don't need to peak at the contained value.The one drawback I anticipate to adding this feature would be the possibility of breaking any code that's relying on the default
object.__bool__behavior to differentiate aFailurefrom eg. aNone... but hopefully, anybody using this library would have their Optionals wrapped in aMaybealready?