Import Upstream version 20180207
[hcoop/debian/mlton.git] / doc / guide / src / MLBasisExamples.adoc
1 MLBasisExamples
2 ===============
3
4 Here are some example uses of <:MLBasis:ML Basis> files.
5
6
7 == Complete program ==
8
9 Suppose your complete program consists of the files `file1.sml`, ...,
10 `filen.sml`, which depend upon libraries `lib1.mlb`, ..., `libm.mlb`.
11
12 ----
13 (* import libraries *)
14 lib1.mlb
15 ...
16 libm.mlb
17
18 (* program files *)
19 file1.sml
20 ...
21 filen.sml
22 ----
23
24 The bases denoted by `lib1.mlb`, ..., `libm.mlb` are merged (bindings
25 of names in later bases take precedence over bindings of the same name
26 in earlier bases), producing a basis in which `file1.sml`, ...,
27 `filen.sml` are elaborated, adding additional bindings to the basis.
28
29
30 == Export filter ==
31
32 Suppose you only want to export certain structures, signatures, and
33 functors from a collection of files.
34
35 ----
36 local
37 file1.sml
38 ...
39 filen.sml
40 in
41 (* export filter here *)
42 functor F
43 structure S
44 end
45 ----
46
47 While `file1.sml`, ..., `filen.sml` may declare top-level identifiers
48 in addition to `F` and `S`, such names are not accessible to programs
49 and libraries that import this `.mlb`.
50
51
52 == Export filter with renaming ==
53
54 Suppose you want an export filter, but want to rename one of the
55 modules.
56
57 ----
58 local
59 file1.sml
60 ...
61 filen.sml
62 in
63 (* export filter, with renaming, here *)
64 functor F
65 structure S' = S
66 end
67 ----
68
69 Note that `functor F` is an abbreviation for `functor F = F`, which
70 simply exports an identifier under the same name.
71
72
73 == Import filter ==
74
75 Suppose you only want to import a functor `F` from one library and a
76 structure `S` from another library.
77
78 ----
79 local
80 lib1.mlb
81 in
82 (* import filter here *)
83 functor F
84 end
85 local
86 lib2.mlb
87 in
88 (* import filter here *)
89 structure S
90 end
91 file1.sml
92 ...
93 filen.sml
94 ----
95
96
97 == Import filter with renaming ==
98
99 Suppose you want to import a structure `S` from one library and
100 another structure `S` from another library.
101
102 ----
103 local
104 lib1.mlb
105 in
106 (* import filter, with renaming, here *)
107 structure S1 = S
108 end
109 local
110 lib2.mlb
111 in
112 (* import filter, with renaming, here *)
113 structure S2 = S
114 end
115 file1.sml
116 ...
117 filen.sml
118 ----
119
120
121 == Full Basis ==
122
123 Since the Modules level of SML is the natural means for organizing
124 program and library components, MLB files provide convenient syntax
125 for renaming Modules level identifiers (in fact, renaming of functor
126 identifiers provides a mechanism that is not available in SML).
127 However, please note that `.mlb` files elaborate to full bases
128 including top-level types and values (including infix status), in
129 addition to structures, signatures, and functors. For example,
130 suppose you wished to extend the <:BasisLibrary:Basis Library> with an
131 `('a, 'b) either` datatype corresponding to a disjoint sum; the type
132 and some operations should be available at the top-level;
133 additionally, a signature and structure provide the complete
134 interface.
135
136 We could use the following files.
137
138 `either-sigs.sml`
139 [source,sml]
140 ----
141 signature EITHER_GLOBAL =
142 sig
143 datatype ('a, 'b) either = Left of 'a | Right of 'b
144 val & : ('a -> 'c) * ('b -> 'c) -> ('a, 'b) either -> 'c
145 val && : ('a -> 'c) * ('b -> 'd) -> ('a, 'b) either -> ('c, 'd) either
146 end
147
148 signature EITHER =
149 sig
150 include EITHER_GLOBAL
151 val isLeft : ('a, 'b) either -> bool
152 val isRight : ('a, 'b) either -> bool
153 ...
154 end
155 ----
156
157 `either-strs.sml`
158 [source,sml]
159 ----
160 structure Either : EITHER =
161 struct
162 datatype ('a, 'b) either = Left of 'a | Right of 'b
163 fun f & g = fn x =>
164 case x of Left z => f z | Right z => g z
165 fun f && g = (Left o f) & (Right o g)
166 fun isLeft x = ((fn _ => true) & (fn _ => false)) x
167 fun isRight x = (not o isLeft) x
168 ...
169 end
170 structure EitherGlobal : EITHER_GLOBAL = Either
171 ----
172
173 `either-infixes.sml`
174 [source,sml]
175 ----
176 infixr 3 & &&
177 ----
178
179 `either-open.sml`
180 [source,sml]
181 ----
182 open EitherGlobal
183 ----
184
185 `either.mlb`
186 ----
187 either-infixes.sml
188 local
189 (* import Basis Library *)
190 $(SML_LIB)/basis/basis.mlb
191 either-sigs.sml
192 either-strs.sml
193 in
194 signature EITHER
195 structure Either
196 either-open.sml
197 end
198 ----
199
200 A client that imports `either.mlb` will have access to neither
201 `EITHER_GLOBAL` nor `EitherGlobal`, but will have access to the type
202 `either` and the values `&` and `&&` (with infix status) in the
203 top-level environment. Note that `either-infixes.sml` is outside the
204 scope of the local, because we want the infixes available in the
205 implementation of the library and to clients of the library.