#include <functional>
#include <utility>
template<template<class ...> class M>
struct Monad {
// return :: a -> m a
template<typename T>
static auto ret(T a) -> M<T>;
// bind :: m a -> (a -> m b) -> m b
template<typename T, typename U>
static auto bind(M<T>, std::function<M<U>(T)>) -> M<U>;
};
// return :: a -> m a
template<template<class...> class M, typename T>
auto ret(T a) -> M<T>
{
return Monad<M>::ret(std::move(a));
}
// (>>=) :: m a -> (a -> m b) -> m b
template<template<class...> class M, typename T, typename F>
auto operator >>= (M<T> ma, F fun) -> decltype(fun(std::declval<T>())) // запутанно, но не знаю, как сделать лучше, чтобы работали лямбды
{
using R = decltype(fun(std::declval<T>()));
return Monad<M>::bind(ma, std::function<R(T)>(std::move(fun)));
}
// (>>) :: m a -> m b -> m b
template<template<class...> class M, typename T, typename U>
auto operator >> (M<T> ma, M<U> mb) -> M<U>
{
return ma >>= [=](T){ return mb; };
}
template<typename T>
struct value { // просто коробка со значением
value(T a)
: x(a)
{}
T x;
};
// специализируем ret
template<>
template<typename T>
auto Monad<value>::ret(T a) -> value<T>
{
return value<T>(a);
}
// специализируем bind
template<>
template<typename T, typename U>
auto Monad<value>::bind(value<T> d, std::function<value<U>(T)> f) -> value<U>
{
return f(d.x);
}
#include <iostream>
auto succ(int x) -> value<int>
{
return ret<value>(x + 1);
}
int main()
{
auto v = (ret<value>(10) >>= succ) >>= succ;
std::cout << v.x << std::endl;
}
I2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDx1dGlsaXR5PgoKdGVtcGxhdGU8dGVtcGxhdGU8Y2xhc3MgLi4uPiBjbGFzcyBNPgpzdHJ1Y3QgTW9uYWQgewogICAgLy8gcmV0dXJuIDo6IGEgLT4gbSBhCiAgICB0ZW1wbGF0ZTx0eXBlbmFtZSBUPgogICAgc3RhdGljIGF1dG8gcmV0KFQgYSkgLT4gTTxUPjsKIAogICAgLy8gYmluZCA6OiBtIGEgLT4gKGEgLT4gbSBiKSAtPiBtIGIKICAgIHRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFU+CiAgICBzdGF0aWMgYXV0byBiaW5kKE08VD4sIHN0ZDo6ZnVuY3Rpb248TTxVPihUKT4pIC0+IE08VT47Cn07CiAKLy8gcmV0dXJuIDo6IGEgLT4gbSBhCnRlbXBsYXRlPHRlbXBsYXRlPGNsYXNzLi4uPiBjbGFzcyBNLCB0eXBlbmFtZSBUPgphdXRvIHJldChUIGEpIC0+IE08VD4KewogICAgcmV0dXJuIE1vbmFkPE0+OjpyZXQoc3RkOjptb3ZlKGEpKTsKfQogCi8vICg+Pj0pIDo6IG0gYSAtPiAoYSAtPiBtIGIpIC0+IG0gYgp0ZW1wbGF0ZTx0ZW1wbGF0ZTxjbGFzcy4uLj4gY2xhc3MgTSwgdHlwZW5hbWUgVCwgdHlwZW5hbWUgRj4KYXV0byBvcGVyYXRvciA+Pj0gKE08VD4gbWEsIEYgZnVuKSAtPiBkZWNsdHlwZShmdW4oc3RkOjpkZWNsdmFsPFQ+KCkpKSAgLy8g0LfQsNC/0YPRgtCw0L3QvdC+LCDQvdC+INC90LUg0LfQvdCw0Y4sINC60LDQuiDRgdC00LXQu9Cw0YLRjCDQu9GD0YfRiNC1LCDRh9GC0L7QsdGLINGA0LDQsdC+0YLQsNC70Lgg0LvRj9C80LHQtNGLCnsKICAgIHVzaW5nIFIgPSBkZWNsdHlwZShmdW4oc3RkOjpkZWNsdmFsPFQ+KCkpKTsKICAgIHJldHVybiBNb25hZDxNPjo6YmluZChtYSwgc3RkOjpmdW5jdGlvbjxSKFQpPihzdGQ6Om1vdmUoZnVuKSkpOwp9CiAKLy8gKD4+KSA6OiBtIGEgLT4gbSBiIC0+IG0gYgp0ZW1wbGF0ZTx0ZW1wbGF0ZTxjbGFzcy4uLj4gY2xhc3MgTSwgdHlwZW5hbWUgVCwgdHlwZW5hbWUgVT4KYXV0byBvcGVyYXRvciA+PiAoTTxUPiBtYSwgTTxVPiBtYikgLT4gTTxVPgp7CiAgICByZXR1cm4gbWEgPj49IFs9XShUKXsgcmV0dXJuIG1iOyB9Owp9CgoKdGVtcGxhdGU8dHlwZW5hbWUgVD4Kc3RydWN0IHZhbHVlIHsgLy8g0L/RgNC+0YHRgtC+INC60L7RgNC+0LHQutCwINGB0L4g0LfQvdCw0YfQtdC90LjQtdC8CiAgICB2YWx1ZShUIGEpCiAgICAgICAgOiB4KGEpCiAgICB7fQogCiAgICBUIHg7Cn07CgovLyDRgdC/0LXRhtC40LDQu9C40LfQuNGA0YPQtdC8IHJldAp0ZW1wbGF0ZTw+CnRlbXBsYXRlPHR5cGVuYW1lIFQ+CmF1dG8gTW9uYWQ8dmFsdWU+OjpyZXQoVCBhKSAtPiB2YWx1ZTxUPgp7CglyZXR1cm4gdmFsdWU8VD4oYSk7Cn0KCi8vINGB0L/QtdGG0LjQsNC70LjQt9C40YDRg9C10LwgYmluZAp0ZW1wbGF0ZTw+CnRlbXBsYXRlPHR5cGVuYW1lIFQsIHR5cGVuYW1lIFU+CmF1dG8gTW9uYWQ8dmFsdWU+OjpiaW5kKHZhbHVlPFQ+IGQsIHN0ZDo6ZnVuY3Rpb248dmFsdWU8VT4oVCk+IGYpIC0+IHZhbHVlPFU+CnsKICAgIHJldHVybiBmKGQueCk7Cn0KCiNpbmNsdWRlIDxpb3N0cmVhbT4KCmF1dG8gc3VjYyhpbnQgeCkgLT4gdmFsdWU8aW50Pgp7CiAgICByZXR1cm4gcmV0PHZhbHVlPih4ICsgMSk7Cn0KIAppbnQgbWFpbigpCnsKICAgIGF1dG8gdiA9IChyZXQ8dmFsdWU+KDEwKSA+Pj0gc3VjYykgPj49IHN1Y2M7CiAKICAgIHN0ZDo6Y291dCA8PCB2LnggPDwgc3RkOjplbmRsOwp9Cg==