File: bindingops.html

package info (click to toggle)
ocaml-doc 4.11-2
  • links: PTS, VCS
  • area: non-free
  • in suites: bookworm, bullseye, sid, trixie
  • size: 20,580 kB
  • sloc: sh: 37; makefile: 11
file content (202 lines) | stat: -rw-r--r-- 10,641 bytes parent folder | download
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
<!DOCTYPE html>
<html>
<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="generator" content="hevea 2.32">

  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
<link rel="stylesheet" type="text/css" href="manual.css">
<title>8.23  Binding operators</title>
</head>
<body>
<a href="generalizedopens.html"><img src="previous_motif.svg" alt="Previous"></a>
<a href="extn.html"><img src="contents_motif.svg" alt="Up"></a>
<hr>
<h2 class="section" id="s:binding-operators"><a class="section-anchor" href="#s:binding-operators" aria-hidden="true"></a>8.23  Binding operators</h2>
<ul>
<li><a href="bindingops.html#ss%3Aletops-rationale">8.23.1  Rationale</a>
</li></ul>
<p>
(Introduced in 4.08.0)</p><div class="syntax"><table class="display dcenter"><tr class="c019"><td class="dcell"><table class="c001 cellpading0"><tr><td class="c018">
<a class="syntax" id="let-operator"><span class="c010">let-operator</span></a></td><td class="c015">::=</td><td class="c017">
 </td></tr>
<tr><td class="c018">&nbsp;</td><td class="c015">∣</td><td class="c017"> <span class="c004">let</span> (<a class="syntax" href="lex.html#core-operator-char"><span class="c010">core-operator-char</span></a> ∣  <span class="c004">&lt;</span>) { <a class="syntax" href="indexops.html#dot-operator-char"><span class="c010">dot-operator-char</span></a> }
 </td></tr>
<tr><td class="c018">&nbsp;</td></tr>
<tr><td class="c018">
<a class="syntax" id="and-operator"><span class="c010">and-operator</span></a></td><td class="c015">::=</td><td class="c017">
 </td></tr>
<tr><td class="c018">&nbsp;</td><td class="c015">∣</td><td class="c017"> <span class="c004">and</span> (<a class="syntax" href="lex.html#core-operator-char"><span class="c010">core-operator-char</span></a> ∣  <span class="c004">&lt;</span>) { <a class="syntax" href="indexops.html#dot-operator-char"><span class="c010">dot-operator-char</span></a> }
 </td></tr>
<tr><td class="c018">&nbsp;</td></tr>
<tr><td class="c018">
<span class="c010">operator-name</span> </td><td class="c015">::=</td><td class="c017">
...
 </td></tr>
<tr><td class="c018">&nbsp;</td><td class="c015">∣</td><td class="c017"> <a class="syntax" href="#let-operator"><span class="c010">let-operator</span></a>
 </td></tr>
<tr><td class="c018">&nbsp;</td><td class="c015">∣</td><td class="c017"> <a class="syntax" href="#and-operator"><span class="c010">and-operator</span></a>
 </td></tr>
<tr><td class="c018">&nbsp;</td></tr>
<tr><td class="c018">
<a class="syntax" href="expr.html#expr"><span class="c010">expr</span></a></td><td class="c015">::=</td><td class="c017">
...
 </td></tr>
<tr><td class="c018">&nbsp;</td><td class="c015">∣</td><td class="c017"> <a class="syntax" href="#let-operator"><span class="c010">let-operator</span></a>  <a class="syntax" href="expr.html#let-binding"><span class="c010">let-binding</span></a>  { <a class="syntax" href="#and-operator"><span class="c010">and-operator</span></a>  <a class="syntax" href="expr.html#let-binding"><span class="c010">let-binding</span></a> }  <span class="c010">in</span>  <a class="syntax" href="expr.html#expr"><span class="c010">expr</span></a>
 </td></tr>
<tr><td class="c018">&nbsp;</td></tr>
</table></td></tr>
</table></div><p>Users can define <em>let operators</em>:</p><div class="caml-example verbatim">

<div class="ocaml">



<div class="pre caml-input"> <span class="ocamlkeyword">let</span> ( <span class="ocamlkeyword">let</span>* ) o f =
   <span class="ocamlkeyword">match</span> o <span class="ocamlkeyword">with</span>
   | None -&gt; None
   | Some x -&gt; f x

 <span class="ocamlkeyword">let</span> return x = Some x</div>



<div class="pre caml-output ok"><span class="ocamlkeyword">val</span> ( <span class="ocamlkeyword">let</span>* ) : 'a option -&gt; ('a -&gt; 'b option) -&gt; 'b option = &lt;<span class="ocamlkeyword">fun</span>&gt;
<span class="ocamlkeyword">val</span> return : 'a -&gt; 'a option = &lt;<span class="ocamlkeyword">fun</span>&gt;</div></div>

</div><p>and then apply them using this convenient syntax:</p><div class="caml-example verbatim">

<div class="ocaml">



<div class="pre caml-input"> <span class="ocamlkeyword">let</span> find_and_sum tbl k1 k2 =
   <span class="ocamlkeyword">let</span>* x1 = Hashtbl.find_opt tbl k1 <span class="ocamlkeyword">in</span>
   <span class="ocamlkeyword">let</span>* x2 = Hashtbl.find_opt tbl k2 <span class="ocamlkeyword">in</span>
     return (x1 + x2)</div>



<div class="pre caml-output ok"><span class="ocamlkeyword">val</span> find_and_sum : ('a, int) Hashtbl.t -&gt; 'a -&gt; 'a -&gt; int option = &lt;<span class="ocamlkeyword">fun</span>&gt;</div></div>

</div><p>which is equivalent to this expanded form:</p><div class="caml-example verbatim">

<div class="ocaml">



<div class="pre caml-input"> <span class="ocamlkeyword">let</span> find_and_sum tbl k1 k2 =
   ( <span class="ocamlkeyword">let</span>* ) (Hashtbl.find_opt tbl k1)
     (<span class="ocamlkeyword">fun</span> x1 -&gt;
        ( <span class="ocamlkeyword">let</span>* ) (Hashtbl.find_opt tbl k2)
          (<span class="ocamlkeyword">fun</span> x2 -&gt; return (x1 + x2)))</div>



<div class="pre caml-output ok"><span class="ocamlkeyword">val</span> find_and_sum : ('a, int) Hashtbl.t -&gt; 'a -&gt; 'a -&gt; int option = &lt;<span class="ocamlkeyword">fun</span>&gt;</div></div>

</div><p>Users can also define <em>and operators</em>:</p><div class="caml-example verbatim">

<div class="ocaml">



<div class="pre caml-input"> <span class="ocamlkeyword">module</span> ZipSeq = <span class="ocamlkeyword">struct</span>

   <span class="ocamlkeyword">type</span> 'a t = 'a Seq.t

   <span class="ocamlkeyword">open</span> Seq

   <span class="ocamlkeyword">let</span> <span class="ocamlkeyword">rec</span> return x =
     <span class="ocamlkeyword">fun</span> () -&gt; Cons(x, return x)

   <span class="ocamlkeyword">let</span> <span class="ocamlkeyword">rec</span> prod a b =
     <span class="ocamlkeyword">fun</span> () -&gt;
       <span class="ocamlkeyword">match</span> a (), b () <span class="ocamlkeyword">with</span>
       | Nil, _ | _, Nil -&gt; Nil
       | Cons(x, a), Cons(y, b) -&gt; Cons((x, y), prod a b)

   <span class="ocamlkeyword">let</span> ( <span class="ocamlkeyword">let</span>+ ) f s = map s f
   <span class="ocamlkeyword">let</span> ( <span class="ocamlkeyword">and</span>+ ) a b = prod a b

 <span class="ocamlkeyword">end</span></div>



<div class="pre caml-output ok"><span class="ocamlkeyword">module</span> ZipSeq :
  <span class="ocamlkeyword">sig</span>
    <span class="ocamlkeyword">type</span> 'a t = 'a Seq.t
    <span class="ocamlkeyword">val</span> return : 'a -&gt; 'a Seq.t
    <span class="ocamlkeyword">val</span> prod : 'a Seq.t -&gt; 'b Seq.t -&gt; ('a * 'b) Seq.t
    <span class="ocamlkeyword">val</span> ( <span class="ocamlkeyword">let</span>+ ) : 'a Seq.t -&gt; ('a -&gt; 'b) -&gt; 'b Seq.t
    <span class="ocamlkeyword">val</span> ( <span class="ocamlkeyword">and</span>+ ) : 'a Seq.t -&gt; 'b Seq.t -&gt; ('a * 'b) Seq.t
  <span class="ocamlkeyword">end</span></div></div>

</div><p>to support the syntax:</p><div class="caml-example verbatim">

<div class="ocaml">



<div class="pre caml-input"> <span class="ocamlkeyword">open</span> ZipSeq
 <span class="ocamlkeyword">let</span> sum3 z1 z2 z3 =
   <span class="ocamlkeyword">let</span>+ x1 = z1
   <span class="ocamlkeyword">and</span>+ x2 = z2
   <span class="ocamlkeyword">and</span>+ x3 = z3 <span class="ocamlkeyword">in</span>
     x1 + x2 + x3</div>



<div class="pre caml-output ok"><span class="ocamlkeyword">val</span> sum3 : int Seq.t -&gt; int Seq.t -&gt; int Seq.t -&gt; int Seq.t = &lt;<span class="ocamlkeyword">fun</span>&gt;</div></div>

</div><p>which is equivalent to this expanded form:</p><div class="caml-example verbatim">

<div class="ocaml">



<div class="pre caml-input"> <span class="ocamlkeyword">open</span> ZipSeq
 <span class="ocamlkeyword">let</span> sum3 z1 z2 z3 =
   ( <span class="ocamlkeyword">let</span>+ ) (( <span class="ocamlkeyword">and</span>+ ) (( <span class="ocamlkeyword">and</span>+ ) z1 z2) z3)
     (<span class="ocamlkeyword">fun</span> ((x1, x2), x3) -&gt; x1 + x2 + x3)</div>



<div class="pre caml-output ok"><span class="ocamlkeyword">val</span> sum3 : int Seq.t -&gt; int Seq.t -&gt; int Seq.t -&gt; int Seq.t = &lt;<span class="ocamlkeyword">fun</span>&gt;</div></div>

</div>
<h3 class="subsection" id="ss:letops-rationale"><a class="section-anchor" href="#ss:letops-rationale" aria-hidden="true"></a>8.23.1  Rationale</h3>
<p>This extension is intended to provide a convenient syntax for working
with monads and applicatives.</p><p>An applicative should provide a module implementing the following
interface:</p><div class="caml-example verbatim">

<div class="ocaml">



<div class="pre caml-input"> <span class="ocamlkeyword">module</span> <span class="ocamlkeyword">type</span> Applicative_syntax = <span class="ocamlkeyword">sig</span>
   <span class="ocamlkeyword">type</span> 'a t
   <span class="ocamlkeyword">val</span> ( <span class="ocamlkeyword">let</span>+ ) : 'a t -&gt; ('a -&gt; 'b) -&gt; 'b t
   <span class="ocamlkeyword">val</span> ( <span class="ocamlkeyword">and</span>+ ): 'a t -&gt; 'b t -&gt; ('a * 'b) t
 <span class="ocamlkeyword">end</span></div></div>

</div><p>where <span class="c003">(let+)</span> is bound to the <span class="c003">map</span> operation and <span class="c003">(and+)</span> is bound to
the monoidal product operation.</p><p>A monad should provide a module implementing the following interface:</p><div class="caml-example verbatim">

<div class="ocaml">



<div class="pre caml-input"> <span class="ocamlkeyword">module</span> <span class="ocamlkeyword">type</span> Monad_syntax = <span class="ocamlkeyword">sig</span>
   <span class="ocamlkeyword">include</span> Applicative_syntax
   <span class="ocamlkeyword">val</span> ( <span class="ocamlkeyword">let</span>* ) : 'a t -&gt; ('a -&gt; 'b t) -&gt; 'b t
   <span class="ocamlkeyword">val</span> ( <span class="ocamlkeyword">and</span>* ): 'a t -&gt; 'b t -&gt; ('a * 'b) t
 <span class="ocamlkeyword">end</span></div></div>

</div><p>where <span class="c003">(let*)</span> is bound to the <span class="c003">bind</span> operation, and <span class="c003">(and*)</span> is also
bound to the monoidal product operation.</p><hr>
<a href="generalizedopens.html"><img src="previous_motif.svg" alt="Previous"></a>
<a href="extn.html"><img src="contents_motif.svg" alt="Up"></a>
</body>
</html>