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<functional>
#include<iostream>
using namespace std;
template<typename T1>
struct Maybe
{
T1 data;
bool valid;
};
template<typename T1, typename T2>
Maybe<T2> operator>>=(Maybe<T1> t, std::function < Maybe<T2> (T1)> &f)
{
Maybe<T2> return_value;
if(t.valid == false)
{
return_value.valid = false;
return return_value;
}
else
{
return f(t.data);
}
}
int main()
{
Maybe<int> x = {5, true};
Maybe<int> y = {29, false};
auto z = [](int a) -> Maybe<int>
{
Maybe<int> s;
s.data = a+1;
s.valid = true;
return s;
};
Maybe<int> p = (x >>= z);
Maybe<int> q = (y >>= z);
cout<<p.data<<' '<<p.valid<<endl;
cout<<q.data<<' '<<q.valid<<endl;
}
When it comes to the actual >>=
call, I am getting a compiler error saying that no match found for >>=
operator. Is my understanding of C++11's lambda functions failing me here?
The type of a lambda isn't a specialization of
std::function
. It's some unamed type. There is a conversion tostd::function
, but that means type deduction won't work for it. So, in this call:The type
T2
can't be deduced:Store the lambda in a
std::function
variable from the start, and it should work:However, it's probably easier to accept any kind of function object. That way you can still use
auto
for the lambda.My 5 cts.
Sample usage:
lengthy
andlength
are "monadic lambdas", i.e.Complete code:
Literally copy & pasting from Haskell style "Maybe" type & *chaining* in C++11
This is probably what you really want to achieve
Noticed that
std::function
have an empty state, we can have the following implementationIn this implementation, all factory methods are free (friend) functions, the
>>
operator (not to be confused with>>
in Haskell, this is the equivalent of>>=
with same associative) is also free, and even not a friend function. Also notice theon
member function, this is used to force any client intended to use aMaybe
instance must be prepared for both cases (Just or Nothing).Here is an example of usage:
The output is
The following works for me: I use decltype to infer the type returned by the lambda:
EDIT
For type safety :
Here's my maybe "monad" that I use quite often in my C++ projects (disclaimer: see the comments below). It's insofar more like the Haskell
Maybe
than your implementation as it only holds an object in thejust
case (pointsmobj
on it), not wasting space if it'snothing
. This also allows it to use of C++11 move semantics, to avoid unnecessary copies. The return types offmap
(fmapped
member function) and>>=
are deduced withdecltype
.The somewhat strange-seeming
begin
andend
iterators allow it to be used in C++11 range-based for loops:outputs only once
7
.