Skip to content

Instantly share code, notes, and snippets.

@jeremyroman
Created December 15, 2011 04:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeremyroman/1479822 to your computer and use it in GitHub Desktop.
Save jeremyroman/1479822 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <string>
#include <vector>
template <template <typename> class M>
class Monad {
public:
template <typename A, typename B, typename Function>
static M<B> monad_bind(M<A> in, Function function);
template <typename T>
static M<T> monad_return(T data);
template <typename T>
static M<T> monad_fail(std::string message);
};
template <typename T>
class lvector : public std::vector<T> {
};
template <>
class Monad<lvector> {
public:
template <typename A, typename B, typename Function>
static lvector<B> monad_bind(lvector<A> in, Function function) {
typename lvector<A>::iterator it_a;
typename lvector<A>::iterator it_b;
lvector<B> result;
for (it_a = in.begin(); it_a != in.end(); ++it_a) {
lvector<B> partial_result = function(*it_a);
for (it_b = partial_result.begin(); it_b != partial_result.end(); ++it_b) {
result.push_back(*it_b);
}
}
return result;
}
template <typename T>
static lvector<T> monad_return(T data) {
lvector<T> result;
result.push_back(data);
return result;
}
template <typename T>
static lvector<T> monad_fail(std::string message) {
return lvector<T>();
}
};
template <template <typename> class M, typename A, typename B, typename Function>
M<B> monad_bind(M<A> in, Function function) {
return Monad<M>::template monad_bind<A, B, Function>(in, function);
}
template <template <typename> class M, typename T>
M<T> monad_return(T data) {
return Monad<M>::template monad_return<T>(data);
}
template <template <typename> class M, typename T>
M<T> monad_fail(std::string message) {
return Monad<M>::template monad_fail<T>(message);
}
template <typename T>
lvector<T> twice(T x) {
lvector<T> result;
result.push_back(x);
result.push_back(x);
return result;
}
int main() {
lvector<int> alpha;
alpha.push_back(1);
alpha.push_back(2);
alpha.push_back(3);
lvector<int> beta = monad_bind<lvector, int, int, lvector<int>(*)(int)>(alpha, twice<int>);
for (lvector<int>::iterator it = beta.begin(); it != beta.end(); ++it) {
std::cout << *it << std::endl;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment