Monads in C++? What a strange name for a post. But it's not so strange. With std::optional C++17 gets a monad. The ranges library from Eric Niebler and the extended futures are also monads. For both, we can hope for in C++20.
Bjarne Stroustrup presented in his Secret Lightning Talk at the Meeting C++ 2016 a few of the concepts of Concepts Lite that we will get with high probability in C++20. There were also mathematical concepts such as ring and monad. My assumption becomes more and more reality. Modern C++ will be hardened for the future.
std::optional
std::optional is inspired by Haskell's Maybe Monad. std::optional that was originally intended to be part of C++14 stands for a calculation that maybe has a value. Therefore, a find algorithm or a query of a hash table has to deal with the fact that the question can not be answered. Often, you use for such cases special values that stand for the presence of no value, so-called no-result. Often we use a null pointer, empty strings of special integer values for no results. This technique is expensive and error-prone because you have to deal with the no-results in a special way. No-results are of the same type as regular results. std::optional has in case of a no-result no value.
Here is a short example.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
// optional.cpp
#include <experimental/optional>
#include <iostream>
#include <vector>
std::experimental::optional<int> getFirst(const std::vector<int>& vec){
if (!vec.empty()) return std::experimental::optional<int>(vec[0]);
else return std::experimental::optional<int>();
}
int main(){
std::vector<int> myVec{1, 2, 3};
std::vector<int> myEmptyVec;
auto myInt= getFirst(myVec);
if (myInt){
std::cout << "*myInt: " << *myInt << std::endl;
std::cout << "myInt.value(): " << myInt.value() << std::endl;
std::cout << "myInt.value_or(2017):" << myInt.value_or(2017) << std::endl;
}
std::cout << std::endl;
auto myEmptyInt= getFirst(myEmptyVec);
if (!myEmptyInt){
std::cout << "myEmptyInt.value_or(2017):" << myEmptyInt.value_or(2017) << std::endl;
}
}
|
std::optional is currently in the namespace experimental. That will change with C++17. I use std::optional in the function getFirst (line 7). getFirst returns the first element if it exists (line 8). If not, you will get a std::optional<int> object (line 9). I use in the main function two vectors. The calls getFirst in line 17 and 27 return the std::optional objects. In case of myInt (line 19), the object has a value; in case of myEmptyInt (Zeile 29), the object has no value. Now I can display the value of myInt (line 20 - 22). The method value_or in line 22 and 30 returns the value or a default value. This is due to the fact whether std::optional has a value.
The screenshot shows the output of the program using the online-compiler at cppreference.com

Extended futures
Modern c++ supports tasks.

Tasks are pairs of std::promise and std::future objects connected by a channel. Both communication endpoints may exist in different threads. The std::promise (sender) pushes its value into the channel the std::future (receiver) is waiting for. The sender can push a value, a notification, or an exception into the channel. I've written a few posts about tasks. Here are the details: Tasks.
The easiest way to create a promise is to use the function std::async. std::async behaves like an asynchronous function call.
int a= 2000
int b= 11;
std::future<int> sum= std::async([=]{ return a+b; });
std::cout << sum.get() << std::endl;
The call std::async performs more actions. First, it creates the communication endpoints promise and future; second, it connects them both via a channel. The lambda function [=]{ return a+b;} is the work package of the promise. It captures arguments a and b from its defining context. The C++ run time decides if the promise will run in the same or in a different thread. Criteria for its decision maybe the size of the work package, the load of the system, or the number of cores.
The future calls sum.get() to get the value from the promise. You can only once call sum.get(). If the promise is not done with its job, the get call will block.
Tasks provide similar and safer handling of threads because they have no shared state that has to be protected. Therefore, race conditions are not possible and deadlocks much rarer. But, the C++11 implementation of futures has a big disadvantage. The composition of std::future objects is not possible. This will not hold true for the extended futures of C++20.
The table shows the functions for extended futures.

Here are a few code snippets from the proposal n3721.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
future<int> f1= async([]() {return 123;});
future<string> f2 = f1.then([](future<int> f) {
return f.get().to_string();
});
future<int> futures[] = {async([]() { return intResult(125); }),
async([]() { return intResult(456); })};
future<vector<future<int>>> any_f = when_any(begin(futures), end(futures));
future<int> futures[] = {async([]() { return intResult(125); }),
async([]() { return intResult(456); })};
future<vector<future<int>>> all_f = when_all(begin(futures), end(futures));
|
The future f2 in line 3 is ready if the future f2 is ready. You can enlarge the chain of futures: f1.then(...).then(...).then(...). The future any_f in line 10 becomes ready if any of its futures become ready. On contrary, the future all_f in line 16 becomes ready, if all its futures become ready.
One question is still not answered. What have futures in common with functional programming? A lot! The extended futures are a monad. I explained in the post Pure Functions the idea of monads. The key idea of a monad is that a monad encapsulates a simple type in an enriched type and supports the compositions of functions on these enriched types. Therefore, the monad needs a function for lifting the simple type into an enriched type. Additionally, a monad needs a function that empowers them to compose functions on enriched types. This is the job for the functions make_ready_future, then, and future<future<T>>. make_ready_future maps a simple type into an enriched type; a so-called monadic value. This function is called identity and has the name return in Haskell. The two functions then and future<future<T>> are equivalent to the bind operator in Haskell. The bind operators job is to transform one monadic value into another monadic value. bind is the function composition in a monad.
Thanks to the method when_any std::future even become a Monad Plus. A Monad Plus requires from its instances that they are monads and have an operator msum. Therefore, std::future supports a kind of an addition operation in C++20.
If you want to know the details, you should read the excellent blog of Bartosz Milelweski and watch his video: "C++17: I See a Monad in Your Future!".
What's next?
In my post Recursion, List Manipulation, and Lazy Evaluation, I wrote: The story about lazy evaluation in C++ is quite short. But I made my conclusion without templates. Thanks to the CRTP idiom and expression templates C++ is lazy. Therefore, I will write in the next post about the infamous CRTP idiom.
Thanks a lot to my Patreon Supporters: Matt Braun, Roman Postanciuc, Tobias Zindl, G Prvulovic, Reinhold Dröge, Abernitzke, Frank Grimm, Sakib, Broeserl, António Pina, Sergey Agafyin, Андрей Бурмистров, Jake, GS, Lawton Shoemake, Animus24, Jozo Leko, John Breland, Venkat Nandam, Jose Francisco, Douglas Tinkham, Kuchlong Kuchlong, Robert Blanch, Truels Wissneth, Kris Kafka, Mario Luoni, Friedrich Huber, lennonli, Pramod Tikare Muralidhara, Peter Ware, Daniel Hufschläger, Alessandro Pezzato, Bob Perry, Satish Vangipuram, Andi Ireland, Richard Ohnemus, Michael Dunsky, Leo Goodstadt, John Wiederhirn, Yacob Cohen-Arazi, Florian Tischler, Robin Furness, Michael Young, Holger Detering, Bernd Mühlhaus, Matthieu Bolt, Stephen Kelley, Kyle Dean, Tusar Palauri, Dmitry Farberov, Juan Dent, George Liao, Daniel Ceperley, Jon T Hess, Stephen Totten, Wolfgang Fütterer, Matthias Grün, Phillip Diekmann, Ben Atakora, and Ann Shatoff.
Thanks in particular to Jon Hess, Lakshman, Christian Wittenhorst, Sherhy Pyton, Dendi Suhubdy, Sudhakar Belagurusamy, Richard Sargeant, Rusty Fleming, John Nebel, Mipko, Alicja Kaminska, and Slavko Radman.
My special thanks to Embarcadero 
My special thanks to PVS-Studio 
My special thanks to Tipi.build 
Seminars
I'm happy to give online seminars or face-to-face seminars worldwide. Please call me if you have any questions.
Bookable (Online)
German
Standard Seminars (English/German)
Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.
- C++ - The Core Language
- C++ - The Standard Library
- C++ - Compact
- C++11 and C++14
- Concurrency with Modern C++
- Design Pattern and Architectural Pattern with C++
- Embedded Programming with Modern C++
- Generic Programming (Templates) with C++
New
- Clean Code with Modern C++
- C++20
Contact Me
- Phone: +49 7472 917441
- Mobil:: +49 176 5506 5086
- Mail: This email address is being protected from spambots. You need JavaScript enabled to view it.
- German Seminar Page: www.ModernesCpp.de
- Mentoring Page: www.ModernesCpp.org
Modernes C++,

Comments
Keep up the good writing.
RSS feed for comments to this post