Created
March 17, 2012 22:37
-
-
Save lcapaldo/2065956 to your computer and use it in GitHub Desktop.
State Monad in C++11
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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