-
Notifications
You must be signed in to change notification settings - Fork 10
/
cont5.cpp
87 lines (76 loc) · 1.55 KB
/
cont5.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include <iostream>
#include <functional>
#include <utility>
#include <boost/optional.hpp>
template<typename T>
class cont
{
template<typename F>
cont(const T& x,F f):x([=](){return x;}),f(f){}
public:
cont(const T& x):x([=](){return x;}){}
template<typename F>
cont(const cont& c,F f):c([=](){return c;}),f(f){}
T run()const
{
return x?
(f?f(x()).run():x()):
f(c().run()).run();
}
std::pair<T,boost::optional<cont>> step()const
{
if(x){
if(f)return f(x()).step();
else return std::make_pair(x(),boost::optional<cont>{});
}
else{
auto res=c().step();
return std::make_pair(
res.first,
res.second?cont{res.second.get(),f}:cont{res.first,f});
}
}
private:
std::function<T()> x;
std::function<cont()> c;
std::function<cont(T)> f;
};
template<template<typename> class M,typename T>
M<T> mreturn(const T& x)
{
return x;
}
template<typename T,typename F>
auto operator>>=(const cont<T>& c, F f)
{
return cont<T>{c,f};
}
#define DO(var,monad,body) \
((monad)>>=[=](const auto& var){ \
return body; \
})
auto fac(int n)
{
std::cout<<"constructing fac("<<n<<")\n";
if(n==0){
return mreturn<cont>(1);
}
else{
return
DO(m,fac(n-1),(
std::cout<<"computing "<<m<<"*"<<n<<"\n",
mreturn<cont>(m*n)
));
}
}
int main()
{
auto f=fac(5);
std::cout<<"fac(5)="<<f.run()<<"\n";
for(;;){
auto p=f.step();
std::cout<<"step: "<<p.first<<"\n";
if(!p.second)break;
f=p.second.get();
}
}