Created
May 20, 2018 13:14
-
-
Save ukoloff/147d4585389660c4b18bf14d971480ae to your computer and use it in GitHub Desktop.
Polymorphic Maybe monad
This file contains hidden or 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 <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