Last active
December 3, 2018 02:53
-
-
Save rizo/795129955f867e166c22e008777464e1 to your computer and use it in GitHub Desktop.
Quick and dirty demonstration of monads in C++.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <assert.h> | |
#include <forward_list> | |
#include <functional> | |
template <typename T> | |
struct option { | |
public: | |
class no_value { }; | |
bool is_some; | |
option(T x) : is_some(true), value(x) { } | |
option() : is_some(false) { } | |
// Helper constructor function for some values. | |
static option<T> some(T value) { | |
return option(value); | |
} | |
// Helper constructor function for none values. | |
static option<T> none() { | |
return option(); | |
} | |
// Forces the unsafe extraction of contained the value. | |
T force() { | |
if (!is_some) throw no_value(); | |
return value; | |
} | |
// Safe application operator: a.then(f) is f called with value of a, only if a != none. | |
option<T> then(std::function<option<T>(T)> f) { | |
if (!is_some) return *this; | |
return f(value); | |
} | |
private: | |
T value; | |
}; | |
// Safe implementation of forward_list::front, returns an option value. | |
template <typename T> | |
option<T> front(std::forward_list<T> l) { | |
if (l.empty()) | |
return option<T>::none(); | |
else | |
return option<T>::some(l.front()); | |
} | |
int main () | |
{ | |
std::forward_list<int> l1 = { 42 }; | |
std::forward_list<int> l2; | |
// We are sure that the result is not none. | |
assert(front(l1).force() == 42); | |
// Take the front of l1 and apply some computation. | |
front(l1) | |
.then([] (int x) { return option<int>::some(x + 1); }) | |
.then([] (int x) { return option<int>::some(x * 2); }) | |
.then([] (int x) { std::cout << "l1 result = " << x << std::endl; | |
return option<int>::none(); }); | |
// Take the front of l2 and apply some computation. | |
// Nothing will happend, because front will be none. | |
front(l2) | |
.then([] (int x) { return option<int>::some(x + 1); }) | |
.then([] (int x) { return option<int>::some(x * 2); }) | |
.then([] (int x) { std::cout << "l2 result = " << x << std::endl; | |
return option<int>::none(); }); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment