4 In <:StandardML:Standard ML>, every type variable is _scoped_ (or
5 bound) at a particular point in the program. A type variable can be
6 either implicitly scoped or explicitly scoped. For example, `'a` is
11 val id: 'a -> 'a = fn x => x
14 and is implicitly scoped in
18 val id = fn x: 'a => x
21 On the other hand, `'a` is explicitly scoped in
25 val 'a id: 'a -> 'a = fn x => x
28 and is explicitly scoped in
32 val 'a id = fn x: 'a => x
35 A type variable can be scoped at a `val` or `fun` declaration. An SML
36 type checker performs scope inference on each top-level declaration to
37 determine the scope of each implicitly scoped type variable. After
38 scope inference, every type variable is scoped at exactly one
39 enclosing `val` or `fun` declaration. Scope inference shows that the
40 first and second example above are equivalent to the third and fourth
41 example, respectively.
43 Section 4.6 of the <:DefinitionOfStandardML:Definition> specifies
44 precisely the scope of an implicitly scoped type variable. A free
45 occurrence of a type variable `'a` in a declaration `d` is said to be
46 _unguarded_ in `d` if `'a` is not part of a smaller declaration. A
47 type variable `'a` is implicitly scoped at `d` if `'a` is unguarded in
48 `d` and `'a` does not occur unguarded in any declaration containing
52 == Scope inference examples ==
58 val id: 'a -> 'a = fn x => x
61 `'a` is unguarded in `val id` and does not occur unguarded in any
62 containing declaration. Hence, `'a` is scoped at `val id` and the
63 declaration is equivalent to the following.
67 val 'a id: 'a -> 'a = fn x => x
74 val f = fn x => let exception E of 'a in E x end
77 `'a` is unguarded in `val f` and does not occur unguarded in any
78 containing declaration. Hence, `'a` is scoped at `val f` and the
79 declaration is equivalent to the following.
83 val 'a f = fn x => let exception E of 'a in E x end
86 * In this example (taken from the <:DefinitionOfStandardML:Definition>),
90 val x: int -> int = let val id: 'a -> 'a = fn z => z in id id end
93 `'a` occurs unguarded in `val id`, but not in `val x`. Hence, `'a` is
94 implicitly scoped at `val id`, and the declaration is equivalent to
99 val x: int -> int = let val 'a id: 'a -> 'a = fn z => z in id id end
107 val f = (fn x: 'a => x) (fn y => y)
110 `'a` occurs unguarded in `val f` and does not occur unguarded in any
111 containing declaration. Hence, `'a` is implicitly scoped at `val f`,
112 and the declaration is equivalent to the following.
116 val 'a f = (fn x: 'a => x) (fn y => y)
119 This does not type check due to the <:ValueRestriction:>.
127 fun g (y: 'a) = if true then x else y
133 `'a` occurs unguarded in `fun g`, not in `fun f`. Hence, `'a` is
134 implicitly scoped at `fun g`, and the declaration is equivalent to
140 fun 'a g (y: 'a) = if true then x else y
146 This fails to type check because `x` and `y` must have the same type,
147 but the `x` occurs outside the scope of the type variable `'a`. MLton
148 reports the following error.
151 Error: z.sml 3.21-3.41.
152 Then and else branches disagree.
155 in: if true then x else y
156 note: type would escape its scope: 'a
157 escape to: z.sml 1.1-6.5
160 This problem could be fixed either by adding an explicit type
161 constraint, as in `fun f (x: 'a)`, or by explicitly scoping `'a`, as
162 in `fun 'a f x = ...`.
165 == Restrictions on type variable scope ==
167 It is not allowed to scope a type variable within a declaration in
168 which it is already in scope (see the last restriction listed on page
169 9 of the <:DefinitionOfStandardML:Definition>). For example, the
170 following program is invalid.
182 MLton reports the following error.
185 Error: z.sml 3.11-3.12.
186 Type variable scoped at an outer declaration: 'a.
187 scoped at: z.sml 1.1-6.6
190 This is an error even if the scoping is implicit. That is, the
191 following program is invalid as well.