Skip to content

Instantly share code, notes, and snippets.

@ukoloff
Created May 20, 2018 13:14
Show Gist options
  • Select an option

  • Save ukoloff/147d4585389660c4b18bf14d971480ae to your computer and use it in GitHub Desktop.

Select an option

Save ukoloff/147d4585389660c4b18bf14d971480ae to your computer and use it in GitHub Desktop.
Polymorphic Maybe monad
#include <cmath>
#include <iostream>
template <class T>
class Maybe {
public:
Maybe(T val) : value(val), ok(true) {}
Maybe() : ok(false) {}
explicit operator bool() const { return ok; }
const T& operator*() const { return value; }
private:
T value;
bool ok;
template <class F>
friend auto operator>>(const Maybe<T>& monad, F&& functor)
-> decltype(functor(monad.value)) {
return monad.ok ? functor(monad.value) : decltype(functor(monad.value))();
}
};
template <class T>
Maybe<T> Sqrt(T value) {
return value >= 0 ? Maybe<T>(sqrt(value)) : Maybe<T>();
}
template <class T>
Maybe<T> Div(T a, T b) {
return b != 0 ? Maybe<T>(a / b) : Maybe<T>();
}
template <class T>
Maybe<T> Log(T value) {
return value > 0 ? Maybe<T>(log(value)) : Maybe<T>();
}
void test() {
double x = 1;
double y = 2;
Maybe<double> result =
Sqrt(x) >> [](double x) { return Sqrt(x); } >>
[](double z) { return Div<float>(1.0, z); } >> [y](double l) {
return Div<float>(1.0, y) >> [](double z) { return Log(double(z)); } >>
[l](double r) { return Maybe<double>(l + r); };
};
if (result) {
std::cout << "Result = " << *result << std::endl;
} else {
std::cout << "Failed!" << std::endl;
}
}
int main() {
test();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment