Import Upstream version 20180207
[hcoop/debian/mlton.git] / doc / guide / src / NumericLiteral.adoc
CommitLineData
7f918cf1
CE
1NumericLiteral
2==============
3
4Numeric literals in <:StandardML:Standard ML> can be written in either
5decimal or hexadecimal notation. Sometimes it can be convenient to
6write numbers down in other bases. Fortunately, using <:Fold:>, it is
7possible to define a concise syntax for numeric literals that allows
8one to write numeric constants in any base and of various types
9(`int`, `IntInf.int`, `word`, and more).
10
11We will define constants `I`, `II`, `W`, and +`+ so
12that, for example,
13[source,sml]
14----
15I 10 `1`2`3 $
16----
17denotes `123:int` in base 10, while
18[source,sml]
19----
20II 8 `2`3 $
21----
22denotes `19:IntInf.int` in base 8, and
23[source,sml]
24----
25W 2 `1`1`0`1 $
26----
27denotes `0w13: word`.
28
29Here is the code.
30
31[source,sml]
32----
33structure Num =
34 struct
35 fun make (op *, op +, i2x) iBase =
36 let
37 val xBase = i2x iBase
38 in
39 Fold.fold
40 ((i2x 0,
41 fn (i, x) =>
42 if 0 <= i andalso i < iBase then
43 x * xBase + i2x i
44 else
45 raise Fail (concat
46 ["Num: ", Int.toString i,
47 " is not a valid\
48 \ digit in base ",
49 Int.toString iBase])),
50 fst)
51 end
52
53 fun I ? = make (op *, op +, id) ?
54 fun II ? = make (op *, op +, IntInf.fromInt) ?
55 fun W ? = make (op *, op +, Word.fromInt) ?
56
57 fun ` ? = Fold.step1 (fn (i, (x, step)) =>
58 (step (i, x), step)) ?
59
60 val a = 10
61 val b = 11
62 val c = 12
63 val d = 13
64 val e = 14
65 val f = 15
66 end
67----
68where
69[source,sml]
70----
71fun fst (x, _) = x
72----
73
74The idea is for the fold to start with zero and to construct the
75result one digit at a time, with each stepper multiplying the previous
76result by the base and adding the next digit. The code is abstracted
77in two different ways for extra generality. First, the `make`
78function abstracts over the various primitive operations (addition,
79multiplication, etc) that are needed to construct a number. This
80allows the same code to be shared for constants `I`, `II`, `W` used to
81write down the various numeric types. It also allows users to add new
82constants for additional numeric types, by supplying the necessary
83arguments to make.
84
85Second, the step function, +&grave;+, is abstracted over the actual
86construction operation, which is created by make, and passed along the
87fold. This allows the same constant, +&grave;+, to be used for all
88numeric types. The alternative approach, having a different step
89function for each numeric type, would be more painful to use.
90
91On the surface, it appears that the code checks the digits dynamically
92to ensure they are valid for the base. However, MLton will simplify
93everything away at compile time, leaving just the final numeric
94constant.