-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathResumableMonad.Multistep.html
More file actions
333 lines (311 loc) · 47.1 KB
/
ResumableMonad.Multistep.html
File metadata and controls
333 lines (311 loc) · 47.1 KB
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<!--
The Multistep implementation of the Resumable monad
parameters will be replaced with the
document title extracted from the <h1> element or
file name, if there is no <h1> heading
-->
<title>Multistep implementation of the Resumable monad
</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Resumable monad with F#">
<meta name="author" content="William Blum">
<script src="http://code.jquery.com/jquery-1.8.0.js"></script>
<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.2.1/js/bootstrap.min.js"></script>
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.2.1/css/bootstrap-combined.min.css" rel="stylesheet">
<link type="text/css" rel="stylesheet" href="content/style.css" />
<script src="content/tips.js" type="text/javascript"></script>
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
<body>
<div class="container">
<div class="masthead">
<ul class="nav nav-pills pull-right">
<li><a href="http://fsharp.org">fsharp.org</a></li>
<li><a href="https://github.com/blumu/ResumableMonad/">github page</a></li>
</ul>
<h3 class="muted">Resumable Monad</h3>
</div>
<hr />
<div class="row">
<div class="span9" id="main">
<h1>Multistep implementation of the Resumable monad</h1>
<p>This module implements the <em>multistep</em> implementation of the resumable monad
where the resumable expression is encoded as a mapping from the trace
history type 'h to the expression's return type 't.</p>
<p>This contrasts with the implementation from <a href="TheResumableMonad.fsx">the original article</a>
where the encoding type <code>'h -> 'h * Option<'t></code>
represents a single state transition. That is a function mapping the existing
trace history to the updated history after taking a single step in the computation.
(i.e. advancing the computation to the next caching point).</p>
<p>The original encoding generates larger types but provides a clean separation
between the definition of the resumable expression monad and the mechanism used
for evaluation and for caching/persistence of the trace history.</p>
<p>The 'mulistep' encoding, defined in the present module, generates smaller types but
requires stronger coupling between the definition of the monadic constructs
and the execution and caching/persistence engine.</p>
<table class="pre"><tr><td class="lines"><pre class="fssnip"><span class="l"> 1: </span>
<span class="l"> 2: </span>
<span class="l"> 3: </span>
<span class="l"> 4: </span>
<span class="l"> 5: </span>
<span class="l"> 6: </span>
<span class="l"> 7: </span>
<span class="l"> 8: </span>
<span class="l"> 9: </span>
<span class="l">10: </span>
<span class="l">11: </span>
<span class="l">12: </span>
<span class="l">13: </span>
<span class="l">14: </span>
<span class="l">15: </span>
<span class="l">16: </span>
<span class="l">17: </span>
<span class="l">18: </span>
<span class="l">19: </span>
</pre></td>
<td class="snippet"><pre class="fssnip highlighted"><code lang="fsharp"><span class="c">/// Multistep resumable monad where a resumable expression is encoded as a </span>
<span class="c">/// mapping from the trace history type 'h to the expression's return type 't.</span>
<span class="k">module</span> <span onmouseout="hideTip(event, 'fs1', 1)" onmouseover="showTip(event, 'fs1', 1)" class="i">ResumableMonad</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs2', 2)" onmouseover="showTip(event, 'fs2', 2)" class="t">Multipstep</span>
<span class="c">/// A resumable computation returning a result of type `'t` with a sequence of</span>
<span class="c">/// caching points encoded by type `'h`.</span>
<span class="c">/// - 'h is a type generated from the monadic expression to encode the history of caching points in the</span>
<span class="c">/// resumable expression. It consists of nested tuples with base elements of type 'a option for each</span>
<span class="c">/// caching point in the computation.</span>
<span class="c">/// - 't is the returned type of the computation</span>
<span class="k">type</span> <span onmouseout="hideTip(event, 'fs3', 3)" onmouseover="showTip(event, 'fs3', 3)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">h</span>,<span class="o">'</span><span class="i">t</span><span class="o">></span> <span class="o">=</span> <span onmouseout="hideTip(event, 'fs3', 4)" onmouseover="showTip(event, 'fs3', 4)" class="p">Resumable</span> <span class="k">of</span> (<span class="o">'</span><span class="i">h</span> <span class="k">-></span> <span class="o">'</span><span class="i">t</span>)
<span class="k">with</span>
<span class="k">member</span> <span class="k">inline</span> <span onmouseout="hideTip(event, 'fs4', 5)" onmouseover="showTip(event, 'fs4', 5)" class="i">R</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs5', 6)" onmouseover="showTip(event, 'fs5', 6)" class="f">resume</span> <span onmouseout="hideTip(event, 'fs6', 7)" onmouseover="showTip(event, 'fs6', 7)" class="i">h</span> <span class="o">=</span>
<span class="k">let</span> (<span onmouseout="hideTip(event, 'fs3', 8)" onmouseover="showTip(event, 'fs3', 8)" class="p">Resumable</span> <span onmouseout="hideTip(event, 'fs7', 9)" onmouseover="showTip(event, 'fs7', 9)" class="f">r</span>) <span class="o">=</span> <span onmouseout="hideTip(event, 'fs4', 10)" onmouseover="showTip(event, 'fs4', 10)" class="i">R</span>
<span onmouseout="hideTip(event, 'fs7', 11)" onmouseover="showTip(event, 'fs7', 11)" class="f">r</span> <span onmouseout="hideTip(event, 'fs6', 12)" onmouseover="showTip(event, 'fs6', 12)" class="i">h</span>
<span class="c">/// Returns the empty history (no caching point are initialized)</span>
<span class="k">member</span> <span class="k">inline</span> <span onmouseout="hideTip(event, 'fs4', 13)" onmouseover="showTip(event, 'fs4', 13)" class="i">R</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs8', 14)" onmouseover="showTip(event, 'fs8', 14)" class="i">initial</span> <span class="o">=</span>
<span class="i">Zero</span><span class="o">.</span><span class="i">getZeroTyped</span><span class="o"><</span><span class="o">'</span><span class="i">h</span><span class="o">></span>
</code></pre></td>
</tr>
</table>
<p>The next type we define is not theoretically required to implement the resumable monad,
we introduce it solely to simplify the type encoding of caching points for large resumable expression.
It allows us to eliminate unneeded occurrences of <code>option unit</code>
in the type encoding <code>'h</code> of large resumable expressions.</p>
<p>The adverse effect is that we need to define multiple version of the bind monadic operators
for each possible combination of the two <code>Resumable</code> type variations: <code>Resumable<'h, 't></code> and <code>Resumable<'t></code>
(If the static constraint <code>not ('h :> unit)</code> could be expressed in F# this would not be needed).</p>
<table class="pre"><tr><td class="lines"><pre class="fssnip"><span class="l"> 1: </span>
<span class="l"> 2: </span>
<span class="l"> 3: </span>
<span class="l"> 4: </span>
<span class="l"> 5: </span>
<span class="l"> 6: </span>
<span class="l"> 7: </span>
<span class="l"> 8: </span>
<span class="l"> 9: </span>
<span class="l">10: </span>
<span class="l">11: </span>
<span class="l">12: </span>
<span class="l">13: </span>
<span class="l">14: </span>
<span class="l">15: </span>
<span class="l">16: </span>
<span class="l">17: </span>
<span class="l">18: </span>
<span class="l">19: </span>
<span class="l">20: </span>
<span class="l">21: </span>
<span class="l">22: </span>
<span class="l">23: </span>
<span class="l">24: </span>
<span class="l">25: </span>
<span class="l">26: </span>
<span class="l">27: </span>
<span class="l">28: </span>
<span class="l">29: </span>
<span class="l">30: </span>
<span class="l">31: </span>
<span class="l">32: </span>
<span class="l">33: </span>
<span class="l">34: </span>
<span class="l">35: </span>
<span class="l">36: </span>
<span class="l">37: </span>
<span class="l">38: </span>
<span class="l">39: </span>
<span class="l">40: </span>
<span class="l">41: </span>
<span class="l">42: </span>
<span class="l">43: </span>
<span class="l">44: </span>
<span class="l">45: </span>
<span class="l">46: </span>
<span class="l">47: </span>
<span class="l">48: </span>
<span class="l">49: </span>
<span class="l">50: </span>
<span class="l">51: </span>
<span class="l">52: </span>
<span class="l">53: </span>
<span class="l">54: </span>
<span class="l">55: </span>
<span class="l">56: </span>
<span class="l">57: </span>
<span class="l">58: </span>
<span class="l">59: </span>
<span class="l">60: </span>
<span class="l">61: </span>
<span class="l">62: </span>
</pre></td>
<td class="snippet"><pre class="fssnip highlighted"><code lang="fsharp"><span class="c">/// A resumable computation of type `'t` with no caching point.</span>
<span class="k">and</span> <span onmouseout="hideTip(event, 'fs3', 15)" onmouseover="showTip(event, 'fs3', 15)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">t</span><span class="o">></span> <span class="o">=</span> <span onmouseout="hideTip(event, 'fs9', 16)" onmouseover="showTip(event, 'fs9', 16)" class="p">Spawnable</span> <span class="k">of</span> (<span onmouseout="hideTip(event, 'fs10', 17)" onmouseover="showTip(event, 'fs10', 17)" class="t">unit</span> <span class="k">-></span> <span class="o">'</span><span class="i">t</span>)
<span class="k">with</span>
<span class="k">member</span> <span class="k">inline</span> <span onmouseout="hideTip(event, 'fs11', 18)" onmouseover="showTip(event, 'fs11', 18)" class="i">R</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs12', 19)" onmouseover="showTip(event, 'fs12', 19)" class="i">resume</span> <span class="o">=</span>
<span class="k">let</span> (<span onmouseout="hideTip(event, 'fs9', 20)" onmouseover="showTip(event, 'fs9', 20)" class="p">Spawnable</span> <span onmouseout="hideTip(event, 'fs13', 21)" onmouseover="showTip(event, 'fs13', 21)" class="f">r</span>) <span class="o">=</span> <span onmouseout="hideTip(event, 'fs11', 22)" onmouseover="showTip(event, 'fs11', 22)" class="i">R</span>
<span onmouseout="hideTip(event, 'fs13', 23)" onmouseover="showTip(event, 'fs13', 23)" class="f">r</span>
<span class="c">/// Return the encapsulated value if present otherwise return the result of the specified `evaluate` function</span>
<span class="k">let</span> <span onmouseout="hideTip(event, 'fs14', 24)" onmouseover="showTip(event, 'fs14', 24)" class="f">getOrEvaluate</span> <span onmouseout="hideTip(event, 'fs15', 25)" onmouseover="showTip(event, 'fs15', 25)" class="f">evaluate</span> <span class="o">=</span> <span class="k">function</span>
| <span onmouseout="hideTip(event, 'fs16', 26)" onmouseover="showTip(event, 'fs16', 26)" class="p">Some</span> <span onmouseout="hideTip(event, 'fs17', 27)" onmouseover="showTip(event, 'fs17', 27)" class="i">cached</span> <span class="k">-></span> <span onmouseout="hideTip(event, 'fs17', 28)" onmouseover="showTip(event, 'fs17', 28)" class="i">cached</span>
| <span onmouseout="hideTip(event, 'fs18', 29)" onmouseover="showTip(event, 'fs18', 29)" class="p">None</span> <span class="k">-></span>
<span onmouseout="hideTip(event, 'fs19', 30)" onmouseover="showTip(event, 'fs19', 30)" class="f">printfn</span> <span class="s">"Cache miss: evaluating..."</span>
<span class="c">// This is where caching/persistence needs to be implemented</span>
<span onmouseout="hideTip(event, 'fs15', 31)" onmouseover="showTip(event, 'fs15', 31)" class="f">evaluate</span>()
<span class="c">/// The syntax builder for the Resumable monadic syntax</span>
<span class="k">type</span> <span onmouseout="hideTip(event, 'fs20', 32)" onmouseover="showTip(event, 'fs20', 32)" class="t">ResumableBuilder</span>() <span class="o">=</span>
<span class="k">member</span> <span class="i">__</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs21', 33)" onmouseover="showTip(event, 'fs21', 33)" class="f">Zero</span><span class="o"><</span><span class="o">'</span><span class="i">t</span><span class="o">></span>() <span class="o">:</span> <span onmouseout="hideTip(event, 'fs3', 34)" onmouseover="showTip(event, 'fs3', 34)" class="t">Resumable</span><span class="o"><</span>_<span class="o">></span> <span class="o">=</span>
<span onmouseout="hideTip(event, 'fs9', 35)" onmouseover="showTip(event, 'fs9', 35)" class="p">Spawnable</span> <span class="o"><|</span> <span class="k">fun</span> () <span class="k">-></span> ()
<span class="k">member</span> <span onmouseout="hideTip(event, 'fs22', 36)" onmouseover="showTip(event, 'fs22', 36)" class="i">__</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs23', 37)" onmouseover="showTip(event, 'fs23', 37)" class="f">Return</span>(<span onmouseout="hideTip(event, 'fs24', 38)" onmouseover="showTip(event, 'fs24', 38)" class="i">x</span><span class="o">:</span><span class="o">'</span><span class="i">t</span>) <span class="o">=</span>
<span onmouseout="hideTip(event, 'fs9', 39)" onmouseover="showTip(event, 'fs9', 39)" class="p">Spawnable</span> <span class="o"><|</span> <span class="k">fun</span> () <span class="k">-></span> <span onmouseout="hideTip(event, 'fs24', 40)" onmouseover="showTip(event, 'fs24', 40)" class="i">x</span>
<span class="k">member</span> <span onmouseout="hideTip(event, 'fs22', 41)" onmouseover="showTip(event, 'fs22', 41)" class="i">__</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs25', 42)" onmouseover="showTip(event, 'fs25', 42)" class="f">Delay</span>(<span onmouseout="hideTip(event, 'fs26', 43)" onmouseover="showTip(event, 'fs26', 43)" class="f">f</span><span class="o">:</span> <span onmouseout="hideTip(event, 'fs10', 44)" onmouseover="showTip(event, 'fs10', 44)" class="t">unit</span> <span class="k">-></span> <span onmouseout="hideTip(event, 'fs3', 45)" onmouseover="showTip(event, 'fs3', 45)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">h</span>,<span class="o">'</span><span class="i">t</span><span class="o">></span>) <span class="o">=</span>
<span onmouseout="hideTip(event, 'fs3', 46)" onmouseover="showTip(event, 'fs3', 46)" class="p">Resumable</span> <span class="o"><|</span> <span class="k">fun</span> <span onmouseout="hideTip(event, 'fs6', 47)" onmouseover="showTip(event, 'fs6', 47)" class="i">h</span> <span class="k">-></span> <span onmouseout="hideTip(event, 'fs26', 48)" onmouseover="showTip(event, 'fs26', 48)" class="f">f</span>()<span class="o">.</span><span class="f">resume</span> <span onmouseout="hideTip(event, 'fs6', 49)" onmouseover="showTip(event, 'fs6', 49)" class="i">h</span>
<span class="k">member</span> <span onmouseout="hideTip(event, 'fs22', 50)" onmouseover="showTip(event, 'fs22', 50)" class="i">__</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs27', 51)" onmouseover="showTip(event, 'fs27', 51)" class="f">Delay</span>(<span onmouseout="hideTip(event, 'fs28', 52)" onmouseover="showTip(event, 'fs28', 52)" class="f">f</span><span class="o">:</span> <span onmouseout="hideTip(event, 'fs10', 53)" onmouseover="showTip(event, 'fs10', 53)" class="t">unit</span> <span class="k">-></span> <span onmouseout="hideTip(event, 'fs3', 54)" onmouseover="showTip(event, 'fs3', 54)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">t</span><span class="o">></span>) <span class="o">=</span>
<span onmouseout="hideTip(event, 'fs9', 55)" onmouseover="showTip(event, 'fs9', 55)" class="p">Spawnable</span> <span class="o"><|</span> <span class="k">fun</span> () <span class="k">-></span> <span onmouseout="hideTip(event, 'fs28', 56)" onmouseover="showTip(event, 'fs28', 56)" class="f">f</span>()<span class="o">.</span><span class="f">resume</span> ()
<span class="c">// Resumable<'u,'a> -> ('a->Resumable<'v, 'b>) -> Resumable<'a option * 'u * 'v, 'b></span>
<span class="k">member</span> <span class="k">inline</span> <span onmouseout="hideTip(event, 'fs22', 57)" onmouseover="showTip(event, 'fs22', 57)" class="i">__</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs29', 58)" onmouseover="showTip(event, 'fs29', 58)" class="f">Bind</span>(<span onmouseout="hideTip(event, 'fs30', 59)" onmouseover="showTip(event, 'fs30', 59)" class="i">f</span><span class="o">:</span><span onmouseout="hideTip(event, 'fs3', 60)" onmouseover="showTip(event, 'fs3', 60)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">u</span>,<span class="o">'</span><span class="i">a</span><span class="o">></span>, <span onmouseout="hideTip(event, 'fs31', 61)" onmouseover="showTip(event, 'fs31', 61)" class="f">g</span><span class="o">:</span><span class="o">'</span><span class="i">a</span><span class="k">-></span><span onmouseout="hideTip(event, 'fs3', 62)" onmouseover="showTip(event, 'fs3', 62)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">v</span>, <span class="o">'</span><span class="i">b</span><span class="o">></span>) <span class="o">=</span>
<span onmouseout="hideTip(event, 'fs3', 63)" onmouseover="showTip(event, 'fs3', 63)" class="p">Resumable</span> <span class="o"><|</span> <span class="k">fun</span> (<span onmouseout="hideTip(event, 'fs32', 64)" onmouseover="showTip(event, 'fs32', 64)" class="i">cached</span>, <span onmouseout="hideTip(event, 'fs33', 65)" onmouseover="showTip(event, 'fs33', 65)" class="i">u</span>, <span onmouseout="hideTip(event, 'fs34', 66)" onmouseover="showTip(event, 'fs34', 66)" class="i">v</span>) <span class="k">-></span> (<span onmouseout="hideTip(event, 'fs32', 67)" onmouseover="showTip(event, 'fs32', 67)" class="i">cached</span> <span class="o">|></span> <span onmouseout="hideTip(event, 'fs14', 68)" onmouseover="showTip(event, 'fs14', 68)" class="f">getOrEvaluate</span> (<span class="k">fun</span> () <span class="k">-></span> <span onmouseout="hideTip(event, 'fs30', 69)" onmouseover="showTip(event, 'fs30', 69)" class="i">f</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs35', 70)" onmouseover="showTip(event, 'fs35', 70)" class="f">resume</span> <span onmouseout="hideTip(event, 'fs33', 71)" onmouseover="showTip(event, 'fs33', 71)" class="i">u</span>) <span class="o">|></span> <span onmouseout="hideTip(event, 'fs31', 72)" onmouseover="showTip(event, 'fs31', 72)" class="f">g</span>)<span class="o">.</span><span class="f">resume</span> <span onmouseout="hideTip(event, 'fs34', 73)" onmouseover="showTip(event, 'fs34', 73)" class="i">v</span>
<span class="c">// Resumable<'u,'a> -> ('a->Resumable<'b>) -> Resumable<'a option * 'u, 'b></span>
<span class="k">member</span> <span class="k">inline</span> <span onmouseout="hideTip(event, 'fs22', 74)" onmouseover="showTip(event, 'fs22', 74)" class="i">__</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs36', 75)" onmouseover="showTip(event, 'fs36', 75)" class="f">Bind</span>(<span onmouseout="hideTip(event, 'fs30', 76)" onmouseover="showTip(event, 'fs30', 76)" class="i">f</span><span class="o">:</span><span onmouseout="hideTip(event, 'fs3', 77)" onmouseover="showTip(event, 'fs3', 77)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">u</span>,<span class="o">'</span><span class="i">a</span><span class="o">></span>, <span onmouseout="hideTip(event, 'fs37', 78)" onmouseover="showTip(event, 'fs37', 78)" class="f">g</span><span class="o">:</span><span class="o">'</span><span class="i">a</span><span class="k">-></span><span onmouseout="hideTip(event, 'fs3', 79)" onmouseover="showTip(event, 'fs3', 79)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">b</span><span class="o">></span>) <span class="o">=</span>
<span onmouseout="hideTip(event, 'fs3', 80)" onmouseover="showTip(event, 'fs3', 80)" class="p">Resumable</span> <span class="o"><|</span> <span class="k">fun</span> (<span onmouseout="hideTip(event, 'fs32', 81)" onmouseover="showTip(event, 'fs32', 81)" class="i">cached</span>, <span onmouseout="hideTip(event, 'fs33', 82)" onmouseover="showTip(event, 'fs33', 82)" class="i">u</span>) <span class="k">-></span> (<span onmouseout="hideTip(event, 'fs32', 83)" onmouseover="showTip(event, 'fs32', 83)" class="i">cached</span> <span class="o">|></span> <span onmouseout="hideTip(event, 'fs14', 84)" onmouseover="showTip(event, 'fs14', 84)" class="f">getOrEvaluate</span> (<span class="k">fun</span> () <span class="k">-></span> <span onmouseout="hideTip(event, 'fs30', 85)" onmouseover="showTip(event, 'fs30', 85)" class="i">f</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs35', 86)" onmouseover="showTip(event, 'fs35', 86)" class="f">resume</span> <span onmouseout="hideTip(event, 'fs33', 87)" onmouseover="showTip(event, 'fs33', 87)" class="i">u</span>) <span class="o">|></span> <span onmouseout="hideTip(event, 'fs37', 88)" onmouseover="showTip(event, 'fs37', 88)" class="f">g</span>)<span class="o">.</span><span class="f">resume</span>()
<span class="c">// Resumable<'a> -> ('a->Resumable<'v, 'b>) -> Resumable<'a option * 'v, 'b> =</span>
<span class="k">member</span> <span class="k">inline</span> <span onmouseout="hideTip(event, 'fs22', 89)" onmouseover="showTip(event, 'fs22', 89)" class="i">__</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs38', 90)" onmouseover="showTip(event, 'fs38', 90)" class="f">Bind</span>(<span onmouseout="hideTip(event, 'fs39', 91)" onmouseover="showTip(event, 'fs39', 91)" class="i">f</span><span class="o">:</span><span onmouseout="hideTip(event, 'fs3', 92)" onmouseover="showTip(event, 'fs3', 92)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">a</span><span class="o">></span>, <span onmouseout="hideTip(event, 'fs31', 93)" onmouseover="showTip(event, 'fs31', 93)" class="f">g</span><span class="o">:</span><span class="o">'</span><span class="i">a</span><span class="k">-></span><span onmouseout="hideTip(event, 'fs3', 94)" onmouseover="showTip(event, 'fs3', 94)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">v</span>, <span class="o">'</span><span class="i">b</span><span class="o">></span>) <span class="o">=</span>
<span onmouseout="hideTip(event, 'fs3', 95)" onmouseover="showTip(event, 'fs3', 95)" class="p">Resumable</span> <span class="o"><|</span> <span class="k">fun</span> (<span onmouseout="hideTip(event, 'fs32', 96)" onmouseover="showTip(event, 'fs32', 96)" class="i">cached</span>, <span onmouseout="hideTip(event, 'fs34', 97)" onmouseover="showTip(event, 'fs34', 97)" class="i">v</span>) <span class="k">-></span> (<span onmouseout="hideTip(event, 'fs32', 98)" onmouseover="showTip(event, 'fs32', 98)" class="i">cached</span> <span class="o">|></span> <span onmouseout="hideTip(event, 'fs14', 99)" onmouseover="showTip(event, 'fs14', 99)" class="f">getOrEvaluate</span> <span onmouseout="hideTip(event, 'fs39', 100)" onmouseover="showTip(event, 'fs39', 100)" class="i">f</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs40', 101)" onmouseover="showTip(event, 'fs40', 101)" class="f">resume</span> <span class="o">|></span> <span onmouseout="hideTip(event, 'fs31', 102)" onmouseover="showTip(event, 'fs31', 102)" class="f">g</span>)<span class="o">.</span><span class="f">resume</span> <span onmouseout="hideTip(event, 'fs34', 103)" onmouseover="showTip(event, 'fs34', 103)" class="i">v</span>
<span class="c">// Resumable<'a> -> ('a->Resumable<'b>) -> Resumable<'a option, 'b> =</span>
<span class="k">member</span> <span class="k">inline</span> <span onmouseout="hideTip(event, 'fs22', 104)" onmouseover="showTip(event, 'fs22', 104)" class="i">__</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs41', 105)" onmouseover="showTip(event, 'fs41', 105)" class="f">Bind</span>(<span onmouseout="hideTip(event, 'fs39', 106)" onmouseover="showTip(event, 'fs39', 106)" class="i">f</span><span class="o">:</span><span onmouseout="hideTip(event, 'fs3', 107)" onmouseover="showTip(event, 'fs3', 107)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">a</span><span class="o">></span>, <span onmouseout="hideTip(event, 'fs37', 108)" onmouseover="showTip(event, 'fs37', 108)" class="f">g</span><span class="o">:</span><span class="o">'</span><span class="i">a</span><span class="k">-></span><span onmouseout="hideTip(event, 'fs3', 109)" onmouseover="showTip(event, 'fs3', 109)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">b</span><span class="o">></span>) <span class="o">=</span>
<span onmouseout="hideTip(event, 'fs3', 110)" onmouseover="showTip(event, 'fs3', 110)" class="p">Resumable</span> <span class="o"><|</span> <span class="k">fun</span> <span onmouseout="hideTip(event, 'fs32', 111)" onmouseover="showTip(event, 'fs32', 111)" class="i">cached</span> <span class="k">-></span> (<span onmouseout="hideTip(event, 'fs32', 112)" onmouseover="showTip(event, 'fs32', 112)" class="i">cached</span> <span class="o">|></span> <span onmouseout="hideTip(event, 'fs14', 113)" onmouseover="showTip(event, 'fs14', 113)" class="f">getOrEvaluate</span> <span onmouseout="hideTip(event, 'fs39', 114)" onmouseover="showTip(event, 'fs39', 114)" class="i">f</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs40', 115)" onmouseover="showTip(event, 'fs40', 115)" class="f">resume</span> <span class="o">|></span> <span onmouseout="hideTip(event, 'fs37', 116)" onmouseover="showTip(event, 'fs37', 116)" class="f">g</span>)<span class="o">.</span><span class="f">resume</span>()
<span class="c">// Resumable<'a> -> ('a->Resumable<'b>) -> Resumable<'b></span>
<span class="k">member</span> <span class="k">inline</span> <span onmouseout="hideTip(event, 'fs22', 117)" onmouseover="showTip(event, 'fs22', 117)" class="i">__</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs42', 118)" onmouseover="showTip(event, 'fs42', 118)" class="f">BindNoCache</span>(<span onmouseout="hideTip(event, 'fs39', 119)" onmouseover="showTip(event, 'fs39', 119)" class="i">f</span><span class="o">:</span><span onmouseout="hideTip(event, 'fs3', 120)" onmouseover="showTip(event, 'fs3', 120)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">a</span><span class="o">></span>, <span onmouseout="hideTip(event, 'fs37', 121)" onmouseover="showTip(event, 'fs37', 121)" class="f">g</span><span class="o">:</span><span class="o">'</span><span class="i">a</span><span class="k">-></span><span onmouseout="hideTip(event, 'fs3', 122)" onmouseover="showTip(event, 'fs3', 122)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">b</span><span class="o">></span>) <span class="o">=</span>
<span onmouseout="hideTip(event, 'fs9', 123)" onmouseover="showTip(event, 'fs9', 123)" class="p">Spawnable</span> <span class="o"><|</span> <span class="k">fun</span> () <span class="k">-></span> (<span onmouseout="hideTip(event, 'fs37', 124)" onmouseover="showTip(event, 'fs37', 124)" class="f">g</span> <span class="o"><|</span> <span onmouseout="hideTip(event, 'fs39', 125)" onmouseover="showTip(event, 'fs39', 125)" class="i">f</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs40', 126)" onmouseover="showTip(event, 'fs40', 126)" class="f">resume</span>())<span class="o">.</span><span class="f">resume</span>()
<span class="c">// Resumable<'u,unit> -> Resumable<'v,'b> -> Resumable<'u * 'v,'b></span>
<span class="k">member</span> <span class="k">inline</span> <span onmouseout="hideTip(event, 'fs22', 127)" onmouseover="showTip(event, 'fs22', 127)" class="i">__</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs43', 128)" onmouseover="showTip(event, 'fs43', 128)" class="f">Combine</span>(<span onmouseout="hideTip(event, 'fs44', 129)" onmouseover="showTip(event, 'fs44', 129)" class="i">p1</span><span class="o">:</span><span onmouseout="hideTip(event, 'fs3', 130)" onmouseover="showTip(event, 'fs3', 130)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">u</span>,<span onmouseout="hideTip(event, 'fs10', 131)" onmouseover="showTip(event, 'fs10', 131)" class="t">unit</span><span class="o">></span>, <span onmouseout="hideTip(event, 'fs45', 132)" onmouseover="showTip(event, 'fs45', 132)" class="i">p2</span><span class="o">:</span><span onmouseout="hideTip(event, 'fs3', 133)" onmouseover="showTip(event, 'fs3', 133)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">v</span>,<span class="o">'</span><span class="i">b</span><span class="o">></span>) <span class="o">=</span>
<span onmouseout="hideTip(event, 'fs3', 134)" onmouseover="showTip(event, 'fs3', 134)" class="p">Resumable</span> <span class="o"><|</span> <span class="k">fun</span> (<span onmouseout="hideTip(event, 'fs33', 135)" onmouseover="showTip(event, 'fs33', 135)" class="i">u</span>, <span onmouseout="hideTip(event, 'fs34', 136)" onmouseover="showTip(event, 'fs34', 136)" class="i">v</span>) <span class="k">-></span> <span onmouseout="hideTip(event, 'fs44', 137)" onmouseover="showTip(event, 'fs44', 137)" class="i">p1</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs35', 138)" onmouseover="showTip(event, 'fs35', 138)" class="f">resume</span> <span onmouseout="hideTip(event, 'fs33', 139)" onmouseover="showTip(event, 'fs33', 139)" class="i">u</span>; <span onmouseout="hideTip(event, 'fs45', 140)" onmouseover="showTip(event, 'fs45', 140)" class="i">p2</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs35', 141)" onmouseover="showTip(event, 'fs35', 141)" class="f">resume</span> <span onmouseout="hideTip(event, 'fs34', 142)" onmouseover="showTip(event, 'fs34', 142)" class="i">v</span>
<span class="c">// Resumable<unit> -> Resumable<'b> -> Resumable<'b></span>
<span class="k">member</span> <span class="k">inline</span> <span onmouseout="hideTip(event, 'fs22', 143)" onmouseover="showTip(event, 'fs22', 143)" class="i">__</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs46', 144)" onmouseover="showTip(event, 'fs46', 144)" class="f">Combine</span>(<span onmouseout="hideTip(event, 'fs47', 145)" onmouseover="showTip(event, 'fs47', 145)" class="i">p1</span><span class="o">:</span><span onmouseout="hideTip(event, 'fs3', 146)" onmouseover="showTip(event, 'fs3', 146)" class="t">Resumable</span><span class="o"><</span><span onmouseout="hideTip(event, 'fs10', 147)" onmouseover="showTip(event, 'fs10', 147)" class="t">unit</span><span class="o">></span>, <span onmouseout="hideTip(event, 'fs48', 148)" onmouseover="showTip(event, 'fs48', 148)" class="i">p2</span><span class="o">:</span><span onmouseout="hideTip(event, 'fs3', 149)" onmouseover="showTip(event, 'fs3', 149)" class="t">Resumable</span><span class="o"><</span><span class="o">'</span><span class="i">b</span><span class="o">></span>) <span class="o">=</span>
<span onmouseout="hideTip(event, 'fs9', 150)" onmouseover="showTip(event, 'fs9', 150)" class="p">Spawnable</span> <span class="o"><|</span> <span class="k">fun</span> () <span class="k">-></span> <span onmouseout="hideTip(event, 'fs47', 151)" onmouseover="showTip(event, 'fs47', 151)" class="i">p1</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs49', 152)" onmouseover="showTip(event, 'fs49', 152)" class="f">resume</span>(); <span onmouseout="hideTip(event, 'fs48', 153)" onmouseover="showTip(event, 'fs48', 153)" class="i">p2</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs50', 154)" onmouseover="showTip(event, 'fs50', 154)" class="f">resume</span>()
<span class="k">member</span> <span onmouseout="hideTip(event, 'fs22', 155)" onmouseover="showTip(event, 'fs22', 155)" class="i">__</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs51', 156)" onmouseover="showTip(event, 'fs51', 156)" class="f">While</span>(<span onmouseout="hideTip(event, 'fs52', 157)" onmouseover="showTip(event, 'fs52', 157)" class="f">condition</span>, <span onmouseout="hideTip(event, 'fs53', 158)" onmouseover="showTip(event, 'fs53', 158)" class="i">body</span><span class="o">:</span><span onmouseout="hideTip(event, 'fs3', 159)" onmouseover="showTip(event, 'fs3', 159)" class="t">Resumable</span><span class="o"><</span><span onmouseout="hideTip(event, 'fs10', 160)" onmouseover="showTip(event, 'fs10', 160)" class="t">unit</span><span class="o">></span>) <span class="o">:</span> <span onmouseout="hideTip(event, 'fs3', 161)" onmouseover="showTip(event, 'fs3', 161)" class="t">Resumable</span><span class="o"><</span><span onmouseout="hideTip(event, 'fs10', 162)" onmouseover="showTip(event, 'fs10', 162)" class="t">unit</span><span class="o">></span> <span class="o">=</span>
<span class="k">if</span> <span onmouseout="hideTip(event, 'fs52', 163)" onmouseover="showTip(event, 'fs52', 163)" class="f">condition</span>() <span class="k">then</span>
<span onmouseout="hideTip(event, 'fs22', 164)" onmouseover="showTip(event, 'fs22', 164)" class="i">__</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs54', 165)" onmouseover="showTip(event, 'fs54', 165)" class="f">BindNoCache</span>(<span onmouseout="hideTip(event, 'fs53', 166)" onmouseover="showTip(event, 'fs53', 166)" class="i">body</span>, (<span class="k">fun</span> () <span class="k">-></span> <span onmouseout="hideTip(event, 'fs22', 167)" onmouseover="showTip(event, 'fs22', 167)" class="i">__</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs55', 168)" onmouseover="showTip(event, 'fs55', 168)" class="f">While</span>(<span onmouseout="hideTip(event, 'fs52', 169)" onmouseover="showTip(event, 'fs52', 169)" class="f">condition</span>, <span onmouseout="hideTip(event, 'fs53', 170)" onmouseover="showTip(event, 'fs53', 170)" class="i">body</span>)))
<span class="k">else</span>
<span onmouseout="hideTip(event, 'fs22', 171)" onmouseover="showTip(event, 'fs22', 171)" class="i">__</span><span class="o">.</span><span onmouseout="hideTip(event, 'fs56', 172)" onmouseover="showTip(event, 'fs56', 172)" class="f">Zero</span>()
</code></pre></td>
</tr>
</table>
<p>We can now declare the computational expression <code>resumable { ... }</code> definining
all the syntactic sugar for the monadic operators defined in <code>ResumableBuilder</code>.</p>
<table class="pre"><tr><td class="lines"><pre class="fssnip"><span class="l">1: </span>
</pre></td>
<td class="snippet"><pre class="fssnip highlighted"><code lang="fsharp"><span class="k">let</span> <span onmouseout="hideTip(event, 'fs57', 173)" onmouseover="showTip(event, 'fs57', 173)" class="i">resumable</span> <span class="o">=</span> <span class="k">new</span> <span onmouseout="hideTip(event, 'fs20', 174)" onmouseover="showTip(event, 'fs20', 174)" class="t">ResumableBuilder</span>()
</code></pre></td>
</tr>
</table>
<h2>Examples</h2>
<p>For usage examples of the resumable monad see the <a href="examples.html">Examples page</a></p>
<h2>Acknowledgement</h2>
<p>I shared my original article on the resumable monad with Tomas Petricek who
gave intersting feedback and in particular clarified the connection with the reader monad in an
<a href="http://fssnip.net/tu">F# snippet</a>.
The enconding used in the mulitsep resumable monad is the same as the one used in Tomas's snippet
however the caching here is performed within the definition of the bind operator as opposed to an external function.</p>
<div class="tip" id="fs1">namespace ResumableMonad</div>
<div class="tip" id="fs2">module Multipstep<br /><br />from ResumableMonad<br /><em><br /><br /> Multistep resumable monad where a resumable expression is encoded as a <br /> mapping from the trace history type 'h to the expression's return type 't.</em></div>
<div class="tip" id="fs3">Multiple items<br />union case Resumable.Resumable: ('h -> 't) -> Resumable<'h,'t><br /><br />--------------------<br />type Resumable<'t> =<br />  | Spawnable of (unit -> 't)<br />  member resume : (unit -> 't)<br /><br />Full name: ResumableMonad.Multipstep.Resumable<_><br /><em><br /><br /> A resumable computation of type `'t` with no caching point.</em><br /><br />--------------------<br />type Resumable<'h,'t> =<br />  | Resumable of ('h -> 't)<br />  member initial : obj<br />  member resume : h:'h -> 't<br /><br />Full name: ResumableMonad.Multipstep.Resumable<_,_><br /><em><br /><br /> A resumable computation returning a result of type `'t` with a sequence of<br /> caching points encoded by type `'h`.<br /> - 'h is a type generated from the monadic expression to encode the history of caching points in the<br />  resumable expression. It consists of nested tuples with base elements of type 'a option for each<br />  caching point in the computation.<br /> - 't is the returned type of the computation</em></div>
<div class="tip" id="fs4">val R : Resumable<'h,'t></div>
<div class="tip" id="fs5">member Resumable.resume : h:'h -> 't<br /><br />Full name: ResumableMonad.Multipstep.Resumable`2.resume</div>
<div class="tip" id="fs6">val h : 'h</div>
<div class="tip" id="fs7">val r : ('h -> 't)</div>
<div class="tip" id="fs8">member Resumable.initial : obj<br /><br />Full name: ResumableMonad.Multipstep.Resumable`2.initial<br /><em><br /><br /> Returns the empty history (no caching point are initialized)</em></div>
<div class="tip" id="fs9">union case Resumable.Spawnable: (unit -> 't) -> Resumable<'t></div>
<div class="tip" id="fs10">type unit = Unit<br /><br />Full name: Microsoft.FSharp.Core.unit</div>
<div class="tip" id="fs11">val R : Resumable<'t></div>
<div class="tip" id="fs12">member Resumable.resume : (unit -> 't)<br /><br />Full name: ResumableMonad.Multipstep.Resumable`1.resume</div>
<div class="tip" id="fs13">val r : (unit -> 't)</div>
<div class="tip" id="fs14">val getOrEvaluate : evaluate:(unit -> 'a) -> _arg1:'a option -> 'a<br /><br />Full name: ResumableMonad.Multipstep.getOrEvaluate<br /><em><br /><br /> Return the encapsulated value if present otherwise return the result of the specified `evaluate` function</em></div>
<div class="tip" id="fs15">val evaluate : (unit -> 'a)</div>
<div class="tip" id="fs16">union case Option.Some: Value: 'T -> Option<'T></div>
<div class="tip" id="fs17">val cached : 'a</div>
<div class="tip" id="fs18">union case Option.None: Option<'T></div>
<div class="tip" id="fs19">val printfn : format:Printf.TextWriterFormat<'T> -> 'T<br /><br />Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn</div>
<div class="tip" id="fs20">Multiple items<br />type ResumableBuilder =<br />  new : unit -> ResumableBuilder<br />  member Bind : f:Resumable<'u,'a> * g:('a -> Resumable<'v,'b>) -> Resumable<('a option * 'u * 'v),'b><br />  member Bind : f:Resumable<'u,'a> * g:('a -> Resumable<'b>) -> Resumable<('a option * 'u),'b><br />  member Bind : f:Resumable<'a> * g:('a -> Resumable<'v,'b>) -> Resumable<('a option * 'v),'b><br />  member Bind : f:Resumable<'a> * g:('a -> Resumable<'b>) -> Resumable<'a option,'b><br />  member BindNoCache : f:Resumable<'a> * g:('a -> Resumable<'b>) -> Resumable<'b><br />  member Combine : p1:Resumable<'u,unit> * p2:Resumable<'v,'b> -> Resumable<('u * 'v),'b><br />  member Combine : p1:Resumable<unit> * p2:Resumable<'b> -> Resumable<'b><br />  member Delay : f:(unit -> Resumable<'h,'t>) -> Resumable<'h,'t><br />  member Delay : f:(unit -> Resumable<'t>) -> Resumable<'t><br />  ...<br /><br />Full name: ResumableMonad.Multipstep.ResumableBuilder<br /><em><br /><br /> The syntax builder for the Resumable monadic syntax</em><br /><br />--------------------<br />new : unit -> ResumableBuilder</div>
<div class="tip" id="fs21">member ResumableBuilder.Zero : unit -> Resumable<unit><br /><br />Full name: ResumableMonad.Multipstep.ResumableBuilder.Zero</div>
<div class="tip" id="fs22">val __ : ResumableBuilder</div>
<div class="tip" id="fs23">member ResumableBuilder.Return : x:'t -> Resumable<'t><br /><br />Full name: ResumableMonad.Multipstep.ResumableBuilder.Return</div>
<div class="tip" id="fs24">val x : 't</div>
<div class="tip" id="fs25">member ResumableBuilder.Delay : f:(unit -> Resumable<'h,'t>) -> Resumable<'h,'t><br /><br />Full name: ResumableMonad.Multipstep.ResumableBuilder.Delay</div>
<div class="tip" id="fs26">val f : (unit -> Resumable<'h,'t>)</div>
<div class="tip" id="fs27">member ResumableBuilder.Delay : f:(unit -> Resumable<'t>) -> Resumable<'t><br /><br />Full name: ResumableMonad.Multipstep.ResumableBuilder.Delay</div>
<div class="tip" id="fs28">val f : (unit -> Resumable<'t>)</div>
<div class="tip" id="fs29">member ResumableBuilder.Bind : f:Resumable<'u,'a> * g:('a -> Resumable<'v,'b>) -> Resumable<('a option * 'u * 'v),'b><br /><br />Full name: ResumableMonad.Multipstep.ResumableBuilder.Bind</div>
<div class="tip" id="fs30">val f : Resumable<'u,'a></div>
<div class="tip" id="fs31">val g : ('a -> Resumable<'v,'b>)</div>
<div class="tip" id="fs32">val cached : 'a option</div>
<div class="tip" id="fs33">val u : 'u</div>
<div class="tip" id="fs34">val v : 'v</div>
<div class="tip" id="fs35">member Resumable.resume : h:'h -> 't</div>
<div class="tip" id="fs36">member ResumableBuilder.Bind : f:Resumable<'u,'a> * g:('a -> Resumable<'b>) -> Resumable<('a option * 'u),'b><br /><br />Full name: ResumableMonad.Multipstep.ResumableBuilder.Bind</div>
<div class="tip" id="fs37">val g : ('a -> Resumable<'b>)</div>
<div class="tip" id="fs38">member ResumableBuilder.Bind : f:Resumable<'a> * g:('a -> Resumable<'v,'b>) -> Resumable<('a option * 'v),'b><br /><br />Full name: ResumableMonad.Multipstep.ResumableBuilder.Bind</div>
<div class="tip" id="fs39">val f : Resumable<'a></div>
<div class="tip" id="fs40">property Resumable.resume: unit -> 'a</div>
<div class="tip" id="fs41">member ResumableBuilder.Bind : f:Resumable<'a> * g:('a -> Resumable<'b>) -> Resumable<'a option,'b><br /><br />Full name: ResumableMonad.Multipstep.ResumableBuilder.Bind</div>
<div class="tip" id="fs42">member ResumableBuilder.BindNoCache : f:Resumable<'a> * g:('a -> Resumable<'b>) -> Resumable<'b><br /><br />Full name: ResumableMonad.Multipstep.ResumableBuilder.BindNoCache</div>
<div class="tip" id="fs43">member ResumableBuilder.Combine : p1:Resumable<'u,unit> * p2:Resumable<'v,'b> -> Resumable<('u * 'v),'b><br /><br />Full name: ResumableMonad.Multipstep.ResumableBuilder.Combine</div>
<div class="tip" id="fs44">val p1 : Resumable<'u,unit></div>
<div class="tip" id="fs45">val p2 : Resumable<'v,'b></div>
<div class="tip" id="fs46">member ResumableBuilder.Combine : p1:Resumable<unit> * p2:Resumable<'b> -> Resumable<'b><br /><br />Full name: ResumableMonad.Multipstep.ResumableBuilder.Combine</div>
<div class="tip" id="fs47">val p1 : Resumable<unit></div>
<div class="tip" id="fs48">val p2 : Resumable<'b></div>
<div class="tip" id="fs49">property Resumable.resume: unit -> unit</div>
<div class="tip" id="fs50">property Resumable.resume: unit -> 'b</div>
<div class="tip" id="fs51">member ResumableBuilder.While : condition:(unit -> bool) * body:Resumable<unit> -> Resumable<unit><br /><br />Full name: ResumableMonad.Multipstep.ResumableBuilder.While</div>
<div class="tip" id="fs52">val condition : (unit -> bool)</div>
<div class="tip" id="fs53">val body : Resumable<unit></div>
<div class="tip" id="fs54">member ResumableBuilder.BindNoCache : f:Resumable<'a> * g:('a -> Resumable<'b>) -> Resumable<'b></div>
<div class="tip" id="fs55">member ResumableBuilder.While : condition:(unit -> bool) * body:Resumable<unit> -> Resumable<unit></div>
<div class="tip" id="fs56">member ResumableBuilder.Zero : unit -> Resumable<unit></div>
<div class="tip" id="fs57">val resumable : ResumableBuilder<br /><br />Full name: ResumableMonad.Multipstep.resumable</div>
</div>
<div class="span3">
<ul class="nav nav-list" id="menu">
<li class="nav-header">Resumable Monad</li>
<li><a href="TheResumableMonad.html">The Resumable Monad</a></li>
<li><a href="Examples.html">Examples</a></li>
<li><a href="ResumableMonad.Multistep.html">ResumableMonad.Multistep</a></li>
<li><a href="ResumableMonad.Multistep.Persisted.html">ResumableMonad.Multistep.Persisted</a></li>
<!--
Here you can add links to other pages of the documentation
The 'divider' element creates a separator and additional
'nav-header' can be used to add sub-headings in the menu:
* <li class="divider"></li>
* <li><a href="...">...</a></li>
* <li class="nav-header">Sub-heading</li>
-->
</ul>
</div>
</div>
</div>
<a href="https://github.com/blumu/ResumableMonad/"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png" alt="Fork me on GitHub"></a>
</body>
</html>