Skip to content

Instantly share code, notes, and snippets.

@Wassasin
Last active July 8, 2016 21:51
Show Gist options
  • Save Wassasin/f83e5c1fabfce3ec2464dac277c46c88 to your computer and use it in GitHub Desktop.
Save Wassasin/f83e5c1fabfce3ec2464dac277c46c88 to your computer and use it in GitHub Desktop.
#include <cstdio>
#include <vector>
template<typename T>
struct monad_vector
{
std::vector<T> v;
static monad_vector<T> ret(T&& x)
{
monad_vector<T> result;
result.v.reserve(1);
result.v.emplace_back(std::move(x));
return result;
}
template<typename F> // F = a -> m b
decltype(auto) bind(F const& f) const
{
using MB = decltype(f(v.front()));
MB result;
for(T const& x : v) {
MB mb = f(x);
std::move(mb.v.begin(), mb.v.end(), std::back_inserter(result.v));
}
return result;
}
monad_vector<T>() = default;
monad_vector<T>(std::initializer_list<T> xs)
: v(xs)
{}
};
template<template <typename> class M, typename F, typename A>
static decltype(auto) ap(M<F> const& mf, M<A> const& ma)
{
return mf.bind([&ma](F f) {
return ma.bind([&f](A a) {
return M<decltype(f(a))>::ret(f(a));
});
});
}
int main() {
auto mx = monad_vector<int>({1, 2, 3});
auto my = monad_vector<int>({2, 3, 4});
// Unfortunately a function explicitly needs to be single argument
auto plus = [](int x){ return [x](int y){ return x + y; }; };
auto mf = monad_vector<decltype(plus)>::ret(std::move(plus));
auto mu = ap(ap(mf, mx), my);
for(auto u : mu.v) {
printf("%i\n", u);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment