Suppose I have two functions that return futures:
std::future<T> foo(int);
std::future<U> bar(T const &);
I want to combine the two functions to a function that takes an int
as parameter and returns a std::future<U>
. How should I write this function? Is it possible to generalize function composition for functions that return futures?
std::future<U> foobar1(int x)
{
auto foo_x = foo(x);
return bar(foo_x.get());
}
This function will block until the future returned by foo
is finished, right? This is clearly not what I want.
std::future<U> foobar2(int x)
{
return std::async([=]()
{
auto foo_x = foo(x);
return bar(foo_x.get()).get();
});
}
It feels silly to call get()
on the future returned by bar
just to have it turned into a new future by std::async
std::future<U> foobar3(int x)
{
return foo(x).then([](std::future<T> f)
{
return bar(f.get()).get();
};
}
Here, again I have to call get()
on the future returned by bar
otherwise I'd have a future<future<U>>
. Is this the correct approach?
What you want is a monad. std::future
is almost but not quite a monad but lacks the ability to properly compose functions by lifting them as you have noticed. For a detailed discussion on this please see this blog post.
The summary is that for C++17 an additional method has been proposed for std::future
: either next
or then
which would take a function to be applied to the future's value once it is available. This would be roughly equivalent to bind
in Haskell for example (note: not std::bind
).
Let's take the two functions:
T foo(int);
U bar(T const &);
Here we have a mapping int -> T -> U
, what you want is to lift this mapping to int -> std::future<T> -> std::future<U>
. What this might look like would be:
int x = 2;
std::async([=](){return foo(x);}).then(bar);
Where then
is a function that automatically maps T -> U
to std::future<T> -> std::future<U>
.
Disclaimer: I am not a Haskell programmer and realise I have probably got everything mixed up. I gladly welcome corrections.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With