C++ is a complicated language, but it doesn't have to be that complicated. Here a simple maybe monad implemented in C++...
#include<iostream>
#include<boost/variant.hpp>
using namespace std;
class Nothing {};
template <class T> class Just
{public:
T val;
Just(T x) : val(x){};
};
template<class T, class F> boost::variant<Nothing, Just<T> >
operator>>=(boost::variant<Nothing, Just<T> > x, F f)
{
return (boost::get<Nothing>(&x)==NULL)
? f(boost::get<Just<T> >(x).val)
: Nothing();
}
template <class T> boost::variant<Nothing, Just<T> >
Return(T x) { return Just<T>(x); }
boost::variant<Nothing, Just<int> > inc(int x) {return Return<int>(x+1);}
int main(int argc, char* argv[])
{
boost::variant<Nothing, Just<int> > foo,bar;
foo = Just<int>(9);
(foo >>= inc) >>= inc;
bar = Nothing();
(bar >>= inc) >>= inc;
return 0;
}
boost::optional
At the expense of making your example look slightly different to the standard Maybe monad, you could have used
boost::optionalas the value type instead ofboost::variant<Nothing, Just<T> >. The "uninitialised" state would be Nothing, while the "initialised" state would be Just.Why the Just class? As far
Why the Just class? As far as I can tell, its only advantage over using boost::variant directly is to allow the "real" value type to also be Nothing. This seems a small comprise for what would be a much simpler syntax.
Disclaimer: I know nothing about monads.