Skip to content

Instantly share code, notes, and snippets.

@bananu7
Created November 12, 2013 23:25
Show Gist options
  • Save bananu7/7440696 to your computer and use it in GitHub Desktop.
Save bananu7/7440696 to your computer and use it in GitHub Desktop.
Monadz
#include <iostream>
#include <functional>
#include <memory>
using std::function;
using std::unique_ptr;
template<typename A>
class Maybe {
public:
unique_ptr<A> a;
template<typename B>
Maybe<B> bind(function< Maybe<B>(A) > f) {
if (a) {
return f(*(a));
}
else {
return nullptr;
}
}
template<typename B>
static Maybe<B> _bind(Maybe<A> x, function< Maybe<B>(A) > f) {
if (x.a) {
return f(*(x.a));
}
else {
return nullptr;
}
}
Maybe(Maybe const& other) {
if (other.a)
a = std::unique_ptr<A>(new A(*(other.a)));
else
a = nullptr;
}
Maybe() {}
Maybe(nullptr_t) {}
};
template<typename A>
Maybe<A> Just(A a) {
Maybe<A> m;
m.a = unique_ptr<A>(new A(a));
return m;
}
template<typename A>
Maybe<A> Nothing() {
return nullptr;
}
template<template<class> class M, class A, class B>
M<B> bind(M<A> x, function< M<B>(A) > f) {
return M<B>::_bind(x, f);
}
template<template<class> class M, class A, class B>
M<B> operator>>(M<A> x, function< M<B>(A) > f) {
return M<B>::_bind(x, f);
}
Maybe<int> half(int x) {
if (x % 2 == 0) {
return Just(x / 2);
}
else {
return Nothing<int>();
}
}
template<typename A>
A fromMaybe(A def, Maybe<A> a) {
if (a.a)
return *(a.a);
else
return def;
}
int main() {
auto x = Just(12);
auto f = std::function<Maybe<int>(int)>(half);
auto result = bind(x, f);
auto result2 = bind(bind(x, f), f);
auto result3 = x.bind(f).bind(f);
auto result4 = Just(12) >> f >> f;
std::cout << fromMaybe(-1, result4);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment