Import Upstream version 20180207
[hcoop/debian/mlton.git] / doc / guide / src / AdmitsEquality.adoc
CommitLineData
7f918cf1
CE
1AdmitsEquality
2==============
3
4A <:TypeConstructor:> admits equality if whenever it is applied to
5equality types, the result is an <:EqualityType:>. This notion enables
6one to determine whether a type constructor application yields an
7equality type solely from the application, without looking at the
8definition of the type constructor. It helps to ensure that
9<:PolymorphicEquality:> is only applied to sensible values.
10
11The definition of admits equality depends on whether the type
12constructor was declared by a `type` definition or a
13`datatype` declaration.
14
15
16== Type definitions ==
17
18For type definition
19
20[source,sml]
21----
22type ('a1, ..., 'an) t = ...
23----
24
25type constructor `t` admits equality if the right-hand side of the
26definition is an equality type after replacing `'a1`, ...,
27`'an` by equality types (it doesn't matter which equality types
28are chosen).
29
30For a nullary type definition, this amounts to the right-hand side
31being an equality type. For example, after the definition
32
33[source,sml]
34----
35type t = bool * int
36----
37
38type constructor `t` admits equality because `bool * int` is
39an equality type. On the other hand, after the definition
40
41[source,sml]
42----
43type t = bool * int * real
44----
45
46type constructor `t` does not admit equality, because `real`
47is not an equality type.
48
49For another example, after the definition
50
51[source,sml]
52----
53type 'a t = bool * 'a
54----
55
56type constructor `t` admits equality because `bool * int`
57is an equality type (we could have chosen any equality type other than
58`int`).
59
60On the other hand, after the definition
61
62[source,sml]
63----
64type 'a t = real * 'a
65----
66
67type constructor `t` does not admit equality because
68`real * int` is not equality type.
69
70We can check that a type constructor admits equality using an
71`eqtype` specification.
72
73[source,sml]
74----
75structure Ok: sig eqtype 'a t end =
76 struct
77 type 'a t = bool * 'a
78 end
79----
80
81[source,sml]
82----
83structure Bad: sig eqtype 'a t end =
84 struct
85 type 'a t = real * int * 'a
86 end
87----
88
89On `structure Bad`, MLton reports the following error.
90----
91Error: z.sml 1.16-1.34.
92 Type in structure disagrees with signature (admits equality): t.
93 structure: type 'a t = [real] * _ * _
94 defn at: z.sml 3.15-3.15
95 signature: [eqtype] 'a t
96 spec at: z.sml 1.30-1.30
97----
98
99The `structure:` section provides an explanation of why the type
100did not admit equality, highlighting the problematic component
101(`real`).
102
103
104== Datatype declarations ==
105
106For a type constructor declared by a datatype declaration to admit
107equality, every <:Variant:variant> of the datatype must admit equality. For
108example, the following datatype admits equality because `bool` and
109`char * int` are equality types.
110
111[source,sml]
112----
113datatype t = A of bool | B of char * int
114----
115
116Nullary constructors trivially admit equality, so that the following
117datatype admits equality.
118
119[source,sml]
120----
121datatype t = A | B | C
122----
123
124For a parameterized datatype constructor to admit equality, we
125consider each <:Variant:variant> as a type definition, and require that the
126definition admit equality. For example, for the datatype
127
128[source,sml]
129----
130datatype 'a t = A of bool * 'a | B of 'a
131----
132
133the type definitions
134
135[source,sml]
136----
137type 'a tA = bool * 'a
138type 'a tB = 'a
139----
140
141both admit equality. Thus, type constructor `t` admits equality.
142
143On the other hand, the following datatype does not admit equality.
144
145[source,sml]
146----
147datatype 'a t = A of bool * 'a | B of real * 'a
148----
149
150As with type definitions, we can check using an `eqtype`
151specification.
152
153[source,sml]
154----
155structure Bad: sig eqtype 'a t end =
156 struct
157 datatype 'a t = A of bool * 'a | B of real * 'a
158 end
159----
160
161MLton reports the following error.
162
163----
164Error: z.sml 1.16-1.34.
165 Type in structure disagrees with signature (admits equality): t.
166 structure: datatype 'a t = B of [real] * _ | ...
167 defn at: z.sml 3.19-3.19
168 signature: [eqtype] 'a t
169 spec at: z.sml 1.30-1.30
170----
171
172MLton indicates the problematic constructor (`B`), as well as
173the problematic component of the constructor's argument.
174
175
176=== Recursive datatypes ===
177
178A recursive datatype like
179
180[source,sml]
181----
182datatype t = A | B of int * t
183----
184
185introduces a new problem, since in order to decide whether `t`
186admits equality, we need to know for the `B` <:Variant:variant> whether
187`t` admits equality. The <:DefinitionOfStandardML:Definition>
188answers this question by requiring a type constructor to admit
189equality if it is consistent to do so. So, in our above example, if
190we assume that `t` admits equality, then the <:Variant:variant>
191`B of int * t` admits equality. Then, since the `A` <:Variant:variant>
192trivially admits equality, so does the type constructor `t`.
193Thus, it was consistent to assume that `t` admits equality, and
194so, `t` does admit equality.
195
196On the other hand, in the following declaration
197
198[source,sml]
199----
200datatype t = A | B of real * t
201----
202
203if we assume that `t` admits equality, then the `B` <:Variant:variant>
204does not admit equality. Hence, the type constructor `t` does not
205admit equality, and our assumption was inconsistent. Hence, `t`
206does not admit equality.
207
208The same kind of reasoning applies to mutually recursive datatypes as
209well. For example, the following defines both `t` and `u` to
210admit equality.
211
212[source,sml]
213----
214datatype t = A | B of u
215and u = C | D of t
216----
217
218But the following defines neither `t` nor `u` to admit
219equality.
220
221[source,sml]
222----
223datatype t = A | B of u * real
224and u = C | D of t
225----
226
227As always, we can check whether a type admits equality using an
228`eqtype` specification.
229
230[source,sml]
231----
232structure Bad: sig eqtype t eqtype u end =
233 struct
234 datatype t = A | B of u * real
235 and u = C | D of t
236 end
237----
238
239MLton reports the following error.
240
241----
242Error: z.sml 1.16-1.40.
243 Type in structure disagrees with signature (admits equality): t.
244 structure: datatype t = B of [_str.u] * [real] | ...
245 defn at: z.sml 3.16-3.16
246 signature: [eqtype] t
247 spec at: z.sml 1.27-1.27
248Error: z.sml 1.16-1.40.
249 Type in structure disagrees with signature (admits equality): u.
250 structure: datatype u = D of [_str.t] | ...
251 defn at: z.sml 4.11-4.11
252 signature: [eqtype] u
253 spec at: z.sml 1.36-1.36
254----