Skip to content

Instantly share code, notes, and snippets.

@lcapaldo
Created March 17, 2012 22:37
Show Gist options
  • Save lcapaldo/2065956 to your computer and use it in GitHub Desktop.
Save lcapaldo/2065956 to your computer and use it in GitHub Desktop.
State Monad in C++11
namespace hask {
struct Unit { };
template<typename S>
struct Stateful {
template<typename V>
struct Value
{
std::function<std::pair<S,V>(S)> runState;
};
};
template<typename S, typename V>
typename Stateful<S>::template Value<V> ret(const V& v)
{
decltype(ret<S>(v)) rv;
rv.runState = [=](S s) { return std::make_pair(s, v); };
return rv;
}
template<typename S>
typename Stateful<S>::template Value<S> get()
{
Stateful<S>::Value<S> rv;
rv.runState = [](S s) { return std::make_pair(s,s); };
return rv;
}
template<typename S>
typename Stateful<S>::template Value<Unit> put(const S& s)
{
Stateful<S>::Value<Unit> rv;
rv.runState = [=](S ) { return std::make_pair(s, Unit()); };
return rv;
}
template<typename S, typename A, typename R>
typename Stateful<S>::template Value<R> bind(typename Stateful<S>::template Value<A> a,
std::function<typename Stateful<S>::template Value<R> (typename A)> f)
{
Stateful<S>::Value<R> rv;
rv.runState = [=](S init) -> std::pair<S,R>
{
std::pair<S, A> p = a.runState(init);
Stateful<S>::Value<R> act2 = f(p.second);
return act2.runState(p.first);
};
return rv;
}
template<typename S, typename A, typename R>
typename Stateful<S>::template Value<R> seq(typename Stateful<S>::template Value<A> a, typename Stateful<S>::template Value<R> r)
{
return bind<S,A,R>(a, [=](A) { return r; });
}
template<typename S, typename V>
typename Stateful<S>::template Value<V> lift0(std::function<V()> f)
{
Stateful<S>::Value<V> rv;
rv.runState = [=](S s) { return std::make_pair(s, f()); };
return rv;
}
}
using namespace hask;
Stateful<int>::template Value<int> getit = get<int>();
std::function< decltype(hask::put<int>(0)) (int) > doit = [](int x) { return hask::put(x + 1); };
Stateful<int>::Value<Unit> incrS = hask::bind<int, int, Unit>(getit, doit);
std::cout << incrS.runState(7).first << std::endl;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment