Boost logo

Boost :

Subject: Re: [boost] Interest in an 'either' library?
From: Eric Niebler (eniebler_at_[hidden])
Date: 2013-06-24 15:19:33


On 13-06-24 11:53 AM, Pierre Talbot wrote:
>>
>> This misses what is, IMO, the most important use case of Haskell's
>> Either monad: automatic error propagation. This would be more useful if
>> there were a way to call a function such that if any of the function's
>> arguments were an Either-in-error, the function would immediately return
>> the error.
>>
>> I implemented something like this. Check out substitution_failure and
>> try_call starting here:
>>
>> https://github.com/ericniebler/proto-0x/blob/master/boost/proto/v5/utility.hpp#L742
>
> In the Expected proposal, there are some methods related to this idea.

Glad it's been considered!

> Actually, the "then" method can be applied on an expected and
> immediately returns the expected if it contains an error. Furthermore,
> you can chain function calls until one of these fail.
>
> Here one of the use-case shown in the proposal:
>
> expected<int> create_and_connect()
> {
> return socket() // call the function socket that creates an expected.
> .then(connect) // Pass the expected handle to connect if it
> contains a value, otherwise just returns it.
> .on_error(error_resolver); // Use the error_resolver if the
> last expected contains an error, otherwise just returns it.
> }
>
> There is maybe two advantages to this then function:
>
> * Chaining multiple calls.
> * A specific error resolver in case of failure.
>
> But it doesn't offer multiple argument check, and that's why we also
> proposed if_all:
>
> if_all(f(), g()).then(h).on_error(error_resolver);
>
> I think this one is much more related to your function.

I'm not sure that hits the mark. What if you want to call h with the
results of calling f and g, but only if f() and g() return non-errors?
That is, what would this look like in your proposed system:

  // if h or g fails, h return immediately.
  h(f(), "hello world", g(), 42);

I'm partial to this:

  // if h or g fails, h return immediately.
  try_call(h)(f(), "hello world", g(), 42);

> I honestly think that if Either goes into Boost, we shouldn't consider
> it as a value or error structure at all. Expected (will) do the job.

Seems a bit excessive to me to have both. If we get Expected, then
Either is unnecessary -- it's just one template alias away from variant.
I don't consider the syntactic niceties of "left" and "right" to be
compelling, and if folks want it, we can provide left and right free
functions for 2-arg variants. But IMO automatic error propagation is the
*only* thing that can make this proposal compelling.

And while I'm thinking of it, I see lots of potential with try_call and
C++14's generic lambdas. Wish I had a compiler that implements them. In
the above, if h is not something that can be passed as a parameter,
you'd want this:

  try_call([](auto &&...args){return
h(forward<decltype-dance>(args)...);})(f(), "hello world", g(), 42);

This begs to be wrapped up in a macro.

-- 
Eric Niebler
Boost.org

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk