I am trying to implement the Maybe monad from Haskell using the lambda functions in C++11 and templates. Here\'s what I have so far
#include
#i
My 5 cts.
Sample usage:
Maybe m1 ("longlonglong");
auto res1 = m1 | lengthy | length;
lengthy
and length
are "monadic lambdas", i.e.
auto length = [] (const string & s) -> Maybe{ return Maybe (s.length()); };
Complete code:
// g++ -std=c++1y answer.cpp
#include
using namespace std;
// ..................................................
// begin LIBRARY
// ..................................................
template
class Maybe {
//
// note: move semantics
// (boxed value is never duplicated)
//
private:
bool is_nothing = false;
public:
T value;
using boxed_type = T;
bool isNothing() const { return is_nothing; }
explicit Maybe () : is_nothing(true) { } // create nothing
//
// naked values
//
explicit Maybe (T && a) : value(std::move(a)), is_nothing(false) { }
explicit Maybe (T & a) : value(std::move(a)), is_nothing(false) { }
//
// boxed values
//
Maybe (Maybe & b) : value(std::move(b.value)), is_nothing(b.is_nothing) { b.is_nothing = true; }
Maybe (Maybe && b) : value(std::move(b.value)), is_nothing(b.is_nothing) { b.is_nothing = true; }
Maybe & operator = (Maybe & b) {
value = std::move(b.value);
(*this).is_nothing = b.is_nothing;
b.is_nothing = true;
return (*this);
}
}; // class
// ..................................................
template
auto operator | (Maybe mi, F f) // chaining (better with | to avoid parentheses)
{
// deduce the type of the monad being returned ...
IT aux;
using OutMonadType = decltype( f(aux) );
using OT = typename OutMonadType::boxed_type;
// just to declare a nothing to return
Maybe nothing;
if (mi.isNothing()) {
return nothing;
}
return f ( mi.value );
} // ()
// ..................................................
template
void showMonad (MO m) {
if ( m.isNothing() ) {
cout << " nothing " << endl;
} else {
cout << " something : ";
cout << m.value << endl;
}
}
// ..................................................
// end LIBRARY
// ..................................................
// ..................................................
int main () {
auto lengthy = [] (const string & s) -> Maybe {
string copyS = s;
if (s.length()>8) {
return Maybe (copyS);
}
return Maybe (); // nothing
};
auto length = [] (const string & s) -> Maybe{ return Maybe (s.length()); };
Maybe m1 ("longlonglong");
Maybe m2 ("short");
auto res1 = m1 | lengthy | length;
auto res2 = m2 | lengthy | length;
showMonad (res1);
showMonad (res2);
} // ()