Import Upstream version 20180207
[hcoop/debian/mlton.git] / doc / guide / src / DefineTypeBeforeUse.adoc
1 DefineTypeBeforeUse
2 ===================
3
4 <:StandardML:Standard ML> requires types to be defined before they are
5 used. Because of type inference, the use of a type can be implicit;
6 hence, this requirement is more subtle than it might appear. For
7 example, the following program is not type correct, because the type
8 of `r` is `t option ref`, but `t` is defined after `r`.
9
10 [source,sml]
11 ----
12 val r = ref NONE
13 datatype t = A | B
14 val () = r := SOME A
15 ----
16
17 MLton reports the following error, indicating that the type defined on
18 line 2 is used on line 1.
19
20 ----
21 Error: z.sml 3.10-3.20.
22 Function applied to incorrect argument.
23 expects: _ * [???] option
24 but got: _ * [t] option
25 in: := (r, SOME A)
26 note: type would escape its scope: t
27 escape from: z.sml 2.10-2.10
28 escape to: z.sml 1.1-1.16
29 Warning: z.sml 1.5-1.5.
30 Type of variable was not inferred and could not be generalized: r.
31 type: ??? option ref
32 in: val r = ref NONE
33 ----
34
35 While the above example is benign, the following example shows how to
36 cast an integer to a function by (implicitly) using a type before it
37 is defined. In the example, the ref cell `r` is of type
38 `t option ref`, where `t` is defined _after_ `r`, as a parameter to
39 functor `F`.
40
41 [source,sml]
42 ----
43 val r = ref NONE
44 functor F (type t
45 val x: t) =
46 struct
47 val () = r := SOME x
48 fun get () = valOf (!r)
49 end
50 structure S1 = F (type t = unit -> unit
51 val x = fn () => ())
52 structure S2 = F (type t = int
53 val x = 13)
54 val () = S1.get () ()
55 ----
56
57 MLton reports the following error.
58
59 ----
60 Warning: z.sml 1.5-1.5.
61 Type of variable was not inferred and could not be generalized: r.
62 type: ??? option ref
63 in: val r = ref NONE
64 Error: z.sml 5.16-5.26.
65 Function applied to incorrect argument.
66 expects: _ * [???] option
67 but got: _ * [t] option
68 in: := (r, SOME x)
69 note: type would escape its scope: t
70 escape from: z.sml 2.17-2.17
71 escape to: z.sml 1.1-1.16
72 Warning: z.sml 6.11-6.13.
73 Type of variable was not inferred and could not be generalized: get.
74 type: unit -> ???
75 in: fun get () = (valOf (! r))
76 Error: z.sml 12.10-12.18.
77 Function not of arrow type.
78 function: [unit]
79 in: (S1.get ()) ()
80 ----