Boost logo

Boost :

Subject: [boost] Final lightweight monad, next gen futures and upcoming AFIO review (was: Re: [next gen futures] Lightweight monad ready
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2015-06-25 21:11:05


On 22 Jun 2015 at 1:43, Niall Douglas wrote:

> Firstly Vicente your three emails contained a ton of gold quality
> observations. From those I have generated this task list:
> [snip]
> Thank you *hugely* for your feedback Vicente. It was extremely
> valuable to me.

For those interested, the final version of lightweight monad hit
github earlier today. Highlights:

monad is now space optimal, consuming as little as two bytes
depending on configuration. monad<void> is now working, plus these
new specialisations were added:

* result<T>: empty/T/error_code (no exception_ptr).
* option<T>: empty/T (no error code nor exceptions).

I chose those names to match the same thing in Rust. They are all
really instantiations of basic_monad<> with a different policy class.
As will be lightweight future<T> next week.

I formalised the logic behind monad into a tribool based ternary
logic, with added C++ 11 tribool implementation based on a constexpr
enum class. This provides a full ternary logic via the usual AND OR
operators etc such that:

if(true_(monad)) // has value
  ...
else if(false_(monad)) // is empty
 ...
else // if(other(monad)) // is errored or excepted
 ...

One can now do make_monad([](Args...){}) and the monad can be called
with (Args...). That also applies to result and option. This opens
some very interesting possibilities for lazy functional programming.

Finally, I added some operator overloads. The bind operator is now
shortcut with operator >>, and operator | and & can be used for
expression binds instead of functional binds like this:

    std::error_code ec;
    monad<int> a(5);
    monad<int> b(a & 6); // a has a value, so become 6
    monad<int> c(b | 4); // b has a value, so remain at 6
    monad<int> d(a & ec); // a has a value, so become errored
    monad<int> e(d & 2); // d does not have a value, so remain
errored
    monad<int> f(d | 2); // d does not have a value, so become 2

I believe, sans bugs, lightweight monad is now finished. I have some
minor todo items, but this is my final intended feature set. Build
impact remains featherweight, space impact is close to optimally low,
and I have even shaved off a few more opcodes from what the compiler
generates for all the operations.

This weekend I'll get started on lightweight future-promise which
derives from monad and indeed is also a basic_monad but with
different implementation policy class. These future-promise ought to
be 98% compatible with the WG21 Concurrency TS spec and will be able
to participate in hetereogeneous when_any/when_all i.e. you can mash
them in with std::future.

It'll likely take me a week to come up with some benchmarks comparing
std::future and my future in a 4-SHA256 engine so you can see the
benefits of the new design. After that I'll replace AFIO's
std::future with these lightweight futures in its public API, and we
should be ready to rock for the 17th July when AFIO's review begins.

Note that only the public user facing API will be refactored to use
these lightweight futures such that you all will review my best
attempt at a final and stable API. I'll leave the existing internal
engine well alone as it's mature and stable until after the community
review, as it will have to be completely redesigned and rewritten to
have optimal performance with these new futures. I don't expect that
to be at all noticeable from external code however, it'll just go
much faster, that's all.

Niall

-- 
ned Productions Limited Consulting
http://www.nedproductions.biz/ 
http://ie.linkedin.com/in/nialldouglas/



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