Subject: Re: [boost] Interest in an 'either' library?
From: David Sankel (camior_at_[hidden])
Date: 2013-06-26 12:21:04
On Tue, Jun 25, 2013 at 9:18 AM, Eric Niebler <eniebler_at_[hidden]> wrote:
> On 6/24/2013 8:55 PM, David Sankel wrote:
> > If we really care about adding a do syntax EDSL, why not make it general
> > purpose like Haskell's version so that it can work with any monad and
> > compose better with other things?
> > either<error, int> result =
> > do(
> > set( _x, getInt ),
> > set( _y, getInt ),
> > doReturn( pure( _x + _y ) ) );
> > If we're going to do that, lets do it generically and completely.
> I've been giving serious thought to that recently. The problem with it,
> however, is that it requires the use of Phoenix-style lambda expressions
> like "_x + _y". (I can only assume you mean for _x and _y to be
> placeholders and not actual values. I can't think of another way to
> implement this.) It seems that for such core functionality, we don't
> want to be saddled by Phoenix's syntax and compile-times, but maybe I'm
I think the 'index' syntax would work around the issues with both
unfamiliarity (people already know bind) and phoenix compilation times.
> Anyhow, yes, I think something like this should exists. Phoenix could
> provide one implementation. FWIW, I just pushed another monad-in-c++ up
> to my github last night (the first link is the state monad, the second
> is an example that uses it):
Cool. I hope you gave bind and '>>' names so they can be used in higher
Let me give that do notation I mentioned in the earlier email a better
do( stmt1, stmt2, stmt3 ).
Do will return some monad parameterized by a type A. stmt1 will define that
Every statement will be an expression that returns a monadic value
(assuming a monadic context). Here are the expression possibilities:
- <normal c++ expression>. For example make_optional( 3 ), or
either<std::string,int>( "Hello World" ) would return monadic values. 3,
and "hello" would not.
- pure( e ). This will wrap the expression into the current monad and
return the result.
- app( e1, e2, e3, ... ). Applies the function returned by e1 to the
values returned by e2, e3, etc..
- _n, gets the unwrapped value of any previous statement.
And optionally, we can add do(...) as another expression type who can refer
to indices in the parent do using de-bruijn indices (_2_1, for example
would get the unwrapped value of the first statement of the parent).
A common case:
either< Error, std::string > result // or whatever monad you like
openNetworkConnection( "192.168.0.1" ),
app( sendMessage, _1, "What is your name" ),
app( getLine, _1 ) );
A somewhat contrived complex example:
either< Error, int > result
app( sqrt, _1_1 )
app( sqrt, _1_2 )
pure( app( plus, _1, _2 ) ) ) ) );
either<Error, int > getIntFromUser();
// This would need to be wrapped into a struct, of course.
template< typename T >
either< Error, T > convertOptionalToError( optional< T > );
boost::optional<int> sqrt( int );
int plus( int, int );
Interestingly enough, normal C++ expressions that return exceptions can be
considered a form of the either monad. I don't know if that fact is useful
But I don't think this obviates the need for the try_call that I was
> suggesting. It is extremely light-weight and let's people write ordinary
> C++ instead of Phoenix. And I think it would be easier to teach to C++
I dunno, it looks pretty odd to me. Do notation seems both simpler and more
powerful. (Just to note for other readers, I tend to write complex examples
to illustrate the power - simple things remain simple though)
>>> 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.
> > I personally find myself using std::pair frequently even though it is
> > just one template alias away from std::tuple. I still think there's a
> > for exposing these commonly-useful simple building blocks. Incidentally,
> > the std::pair monad is also interesting.
> I use it too. But I tend to believe that if C++ got std::tuple first,
> std::pair really would just be a template alias for a 2-tuple. That's
> obviously just my opinion, though.
I'm down for making either a template alias for a 2-variant where the
2-variant has special names to give easy access to left and right.
-- David Sankel
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk