Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: result.apply #215

Open
Hugovdberg opened this issue Jul 28, 2024 · 2 comments
Open

Feature request: result.apply #215

Hugovdberg opened this issue Jul 28, 2024 · 2 comments

Comments

@Hugovdberg
Copy link

Hugovdberg commented Jul 28, 2024

Is your feature request related to a problem? Please describe.
As far as I can tell, expression currently has no way of combining two Result objects.

Describe the solution you'd like
A common way of doing this in functional programming is called apply, which takes a Result[(a)->(b), E] and returns a (Result[a, E])->(Result[b, E]).

_a = TypeVar("_a")
_b = TypeVar("_b")
_Exception = TypeVar("_Exception", bound=Exception)

def result_apply_(
    f: result.Result[Callable[[_a], _b], _Exception], x: result.Result[_a, _Exception]
) -> result.Result[_b, _Exception]:
    match f, x:
        case result.Result(tag="ok", ok=func), result.Result(tag="ok", ok=value):
            return result.Result[_b, _Exception].Ok(func(value))
        case result.Result(tag="error", error=err), _:
            return result.Result[_b, _Exception].Error(err)
        case _, result.Result(tag="error", error=err):
            return result.Result[_b, _Exception].Error(err)
        case _, _:
            raise AssertionError("Should not match")

result_apply = curry(1)(result_apply_)
result_apply_to = curry_flip(1)(result_apply_)

This is not included in FSharp.Core, which is probably the reason why it is not included in expression, but then again it is a little harder to implement as an end user in python than it is in F#. So it would be really nice to have this included in the library.

[Edit] defined both result_apply for the case where you pipe a value to a callable:

pipe(
    Result.Ok(a),
    result_apply(Result.Ok(lambda a: a))
)

and a result_apply_to where you pipe a callable to a Result[value]:

pipe(
    Result.Ok(lambda a: a),
    result_apply_to(Result.Ok(a))
)
@u3kkasha
Copy link
Contributor

u3kkasha commented Sep 8, 2024

@Hugovdberg
Copy link
Author

That is subtly different, in the case of apply the mapper itself is inside a Result monad and therefore not directly usable in map2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants