Expression icon indicating copy to clipboard operation
Expression copied to clipboard

Feature request: result.apply

Open Hugovdberg opened this issue 6 months ago • 2 comments

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))
)

Hugovdberg avatar Jul 28 '24 17:07 Hugovdberg