The purpose of successor ML, or sML for short, is to provide a vehicle for the continued evolution of ML, using Standard ML as a starting point. The intention is for successor ML to be a living, evolving dialect of ML that is responsive to community needs and advances in language design, implementation, and semantics.
SuccessorML Features in MLton
The following SuccessorML features have been implemented in MLton.
The features are disabled by default, and may be enabled utilizing the
feature’s corresponding ML Basis annotation
which is listed directly after the feature name. In addition, the
allowSuccessorML {false|true} annotation can be used to
simultaneously enable all of the features.
-
doDeclarations:allowDoDecls {false|true}Allow a
do expdeclaration form, which evaluates exp for its side effects. The following example uses adodeclaration:do print "Hello world.\n"and is equivalent to:
val () = print "Hello world.\n" -
Extended Constants:
allowExtendedConsts {false|true}Allow or disallow all of the extended constants features. This is a proxy for all of the following annotations.
-
Extended Numeric Constants:
allowExtendedNumConsts {false|true}Allow underscores as a separator in numeric constants and allow binary integer and word constants.
Underscores in a numeric constant must occur between digits and consecutive underscores are allowed.
Binary integer constants use the prefix
0band binary word constants use the prefix0wb.The following example uses extended numeric constants (although it may be incorrectly syntax highlighted):
val pb = 0b10101 val nb = ~0b10_10_10 val wb = 0wb1010 val i = 4__327__829 val r = 6.022_140_9e23 -
Extended Text Constants:
allowExtendedTextConsts {false|true}Allow characters with integer codes ≥ 128 and ≤ 247 that correspond to syntactically well-formed UTF-8 byte sequences in text constants.
Any 1, 2, 3, or 4 byte sequence that can be properly decoded to a binary number according to the UTF-8 encoding/decoding scheme is allowed in a text constant (but invalid sequences are not explicitly rejected) and denotes the corresponding sequence of characters with integer codes ≥ 128 and ≤ 247. This feature enables "UTF-8 convenience" (but not comprehensive Unicode support); in particular, it allows one to copy text from a browser and paste it into a string constant in an editor and, furthermore, if the string is printed to a terminal, then will (typically) appear as the original text. The following example uses UTF-8 byte sequences:
val s1 : String.string = "\240\159\130\161" val s2 : String.string = "🂡" val _ = print ("s1 --> " ^ s1 ^ "\n") val _ = print ("s2 --> " ^ s2 ^ "\n") val _ = print ("String.size s1 --> " ^ Int.toString (String.size s1) ^ "\n") val _ = print ("String.size s2 --> " ^ Int.toString (String.size s2) ^ "\n") val _ = print ("s1 = s2 --> " ^ Bool.toString (s1 = s2) ^ "\n")and, when compiled and executed, will display:
s1 --> 🂡 s2 --> 🂡 String.size s1 --> 4 String.size s2 --> 4 s1 = s2 --> true
Note that the
String.stringtype corresponds to any sequence of 8-bit values, including invalid UTF-8 sequences; hence the string constant"\192"(a UTF-8 leading byte with no UTF-8 continuation byte) is valid. Similarly, theChar.chartype corresponds to a single 8-bit value; hence the char constant#"α"is not valid, as the text constant"α"denotes a sequence of two 8-bit values.
-
-
Line Comments:
allowLineComments {false|true}Allow line comments beginning with the token
(*). The following example uses a line comment:(*) This is a line commentLine comments properly nest within block comments. The following example uses line comments nested within block comments:
(* val x = 4 (*) This is a line comment *) (* val y = 5 (*) This is a line comment *) *) -
Optional Pattern Bars:
allowOptBar {false|true}Allow a bar to appear before the first match rule of a
case,fn, orhandleexpression, allow a bar to appear before the first function-value binding of afundeclaration, and allow a bar to appear before the first constructor binding or description of adatatypedeclaration or specification. The following example uses leading bars in adatatypedeclaration, afundeclaration, and acaseexpression:datatype t = | C | B | A fun | f NONE = 0 | f (SOME t) = (case t of | A => 1 | B => 2 | C => 3)By eliminating the special case of the first element, this feature allows for simpler refactoring (e.g., sorting the lines of the
datatypedeclaration’s constructor bindings to put the constructors in alphabetical order). -
Optional Semicolons:
allowOptSemicolon {false|true}Allow a semicolon to appear after the last expression in a sequence or
let-body expression. The following example uses a trailing semicolon in the body of aletexpression:fun h z = let val x = 3 * z in f x ; g x ; endBy eliminating the special case of the last element, this feature allows for simpler refactoring.
-
Disjunctive (Or) Patterns:
allowOrPats {false|true}Allow disjunctive (a.k.a., "or") patterns of the form
pat1 | pat2, which matches a value that matches eitherpat1orpat2. Disjunctive patterns have lower precedence thanaspatterns and constraint patterns, much asorelseexpressions have lower precedence thanandalsoexpressions and constraint expressions. Both sub-patterns of a disjunctive pattern must bind the same variables with the same types. The following example uses disjunctive patterns:datatype t = A of int | B of int | C of int | D of int * int | E of int * int fun f t = case t of A x | B x | C x => x + 1 | D (x, _) | E (_, x) => x * 2 -
Record Punning Expressions:
allowRecordPunExps {false|true}Allow record punning expressions, whereby an identifier
vidas an expression row in a record expression denotes the expression rowvid = vid(i.e., treating a label as a variable). The following example uses record punning expressions (and also record punning patterns):fun incB r = case r of {a, b, c} => {a, b = b + 1, c}and is equivalent to:
fun incB r = case r of {a = a, b = b, c = c} => {a = a, b = b + 1, c = c} -
withtypein Signatures:allowSigWithtype {false|true}Allow
withtypeto modify adatatypespecification in a signature. The following example useswithtypein a signature (and alsowithtypein a declaration):signature STREAM = sig datatype 'a u = Nil | Cons of 'a * 'a t withtype 'a t = unit -> 'a u end structure Stream : STREAM = struct datatype 'a u = Nil | Cons of 'a * 'a t withtype 'a t = unit -> 'a u endand is equivalent to:
signature STREAM = sig datatype 'a u = Nil | Cons of 'a * (unit -> 'a u) type 'a t = unit -> 'a u end structure Stream : STREAM = struct datatype 'a u = Nil | Cons of 'a * (unit -> 'a u) type 'a t = unit -> 'a u end -
Vector Expressions and Patterns:
allowVectorExpsAndPats {false|true}Allow or disallow vector expressions and vector patterns. This is a proxy for all of the following annotations.
-
Vector Expressions:
allowVectorExps {false|true}Allow vector expressions of the form
#[exp0, exp1, …, expn-1](where n ≥ 0). The expression has typeÏ„ vectorwhen each expressionexpihas typeÏ„. -
Vector Patterns:
allowVectorPats {false|true}Allow vector patterns of the form
#[pat0, pat1, …, patn-1](where n ≥ 0). The pattern matches values of typeÏ„ vectorwhen each patternpatimatches values of typeÏ„.
-