Backport from sid to buster
[hcoop/debian/mlton.git] / doc / guide / src / StandardMLGotchas.adoc
CommitLineData
7f918cf1
CE
1StandardMLGotchas
2=================
3:toc:
4
5This page contains brief explanations of some recurring sources of
6confusion and problems that SML newbies encounter.
7
8Many confusions about the syntax of SML seem to arise from the use of
9an interactive REPL (Read-Eval Print Loop) while trying to learn the
10basics of the language. While writing your first SML programs, you
11should keep the source code of your programs in a form that is
12accepted by an SML compiler as a whole.
13
14== The `and` keyword ==
15
16It is a common mistake to misuse the `and` keyword or to not know how
17to introduce mutually recursive definitions. The purpose of the `and`
18keyword is to introduce mutually recursive definitions of functions
19and datatypes. For example,
20
21[source,sml]
22----
23fun isEven 0w0 = true
24 | isEven 0w1 = false
25 | isEven n = isOdd (n-0w1)
26and isOdd 0w0 = false
27 | isOdd 0w1 = true
28 | isOdd n = isEven (n-0w1)
29----
30
31and
32
33[source,sml]
34----
35datatype decl = VAL of id * pat * expr
36 (* | ... *)
37 and expr = LET of decl * expr
38 (* | ... *)
39----
40
41You can also use `and` as a shorthand in a couple of other places, but
42it is not necessary.
43
44== Constructed patterns ==
45
46It is a common mistake to forget to parenthesize constructed patterns
47in `fun` bindings. Consider the following invalid definition:
48
49[source,sml]
50----
51fun length nil = 0
52 | length h :: t = 1 + length t
53----
54
55The pattern `h :: t` needs to be parenthesized:
56
57[source,sml]
58----
59fun length nil = 0
60 | length (h :: t) = 1 + length t
61----
62
63The parentheses are needed, because a `fun` definition may have
64multiple consecutive constructed patterns through currying.
65
66The same applies to nonfix constructors. For example, the parentheses
67in
68
69[source,sml]
70----
71fun valOf NONE = raise Option
72 | valOf (SOME x) = x
73----
74
75are required. However, the outermost constructed pattern in a `fn` or
76`case` expression need not be parenthesized, because in those cases
77there is always just one constructed pattern. So, both
78
79[source,sml]
80----
81val valOf = fn NONE => raise Option
82 | SOME x => x
83----
84
85and
86
87[source,sml]
88----
89fun valOf x = case x of
90 NONE => raise Option
91 | SOME x => x
92----
93
94are fine.
95
96== Declarations and expressions ==
97
98It is a common mistake to confuse expressions and declarations.
99Normally an SML source file should only contain declarations. The
100following are declarations:
101
102[source,sml]
103----
104datatype dt = ...
105fun f ... = ...
106functor Fn (...) = ...
107infix ...
108infixr ...
109local ... in ... end
110nonfix ...
111open ...
112signature SIG = ...
113structure Struct = ...
114type t = ...
115val v = ...
116----
117
118Note that
119
120[source,sml]
121----
122let ... in ... end
123----
124
125isn't a declaration.
126
127To specify a side-effecting computation in a source file, you can write:
128
129[source,sml]
130----
131val () = ...
132----
133
134
135== Equality types ==
136
137SML has a fairly intricate built-in notion of equality. See
138<:EqualityType:> and <:EqualityTypeVariable:> for a thorough
139discussion.
140
141
142== Nested cases ==
143
144It is a common mistake to write nested case expressions without the
145necessary parentheses. See <:UnresolvedBugs:> for a discussion.
146
147
148== (op *) ==
149
150It used to be a common mistake to parenthesize `op *` as `(op *)`.
151Before SML'97, `*)` was considered a comment terminator in SML and
152caused a syntax error. At the time of writing, <:SMLNJ:SML/NJ> still
153rejects the code. An extra space may be used for portability:
154`(op * )`. However, parenthesizing `op` is redundant, even though it
155is a widely used convention.
156
157
158== Overloading ==
159
160A number of standard operators (`+`, `-`, `~`, `*`, `<`, `>`, ...) and
161numeric constants are overloaded for some of the numeric types (`int`,
162`real`, `word`). It is a common surprise that definitions using
163overloaded operators such as
164
165[source,sml]
166----
167fun min (x, y) = if y < x then y else x
168----
169
170are not overloaded themselves. SML doesn't really support
171(user-defined) overloading or other forms of ad hoc polymorphism. In
172cases such as the above where the context doesn't resolve the
173overloading, expressions using overloaded operators or constants get
174assigned a default type. The above definition gets the type
175
176[source,sml]
177----
178val min : int * int -> int
179----
180
181See <:Overloading:> and <:TypeIndexedValues:> for further discussion.
182
183
184== Semicolons ==
185
186It is a common mistake to use redundant semicolons in SML code. This
187is probably caused by the fact that in an SML REPL, a semicolon (and
188enter) is used to signal the REPL that it should evaluate the
189preceding chunk of code as a unit. In SML source files, semicolons
190are really needed in only two places. Namely, in expressions of the
191form
192
193[source,sml]
194----
195(exp ; ... ; exp)
196----
197
198and
199
200[source,sml]
201----
202let ... in exp ; ... ; exp end
203----
204
205Note that semicolons act as expression (or declaration) separators
206rather than as terminators.
207
208
209== Stale bindings ==
210
211{empty}
212
213
214== Unresolved records ==
215
216{empty}
217
218
219== Value restriction ==
220
221See <:ValueRestriction:>.
222
223
224== Type Variable Scope ==
225
226See <:TypeVariableScope:>.