Skip to content

Instantly share code, notes, and snippets.

@rizo
Last active December 3, 2018 02:53
Show Gist options
  • Save rizo/795129955f867e166c22e008777464e1 to your computer and use it in GitHub Desktop.
Save rizo/795129955f867e166c22e008777464e1 to your computer and use it in GitHub Desktop.
Quick and dirty demonstration of monads in C++.
#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