[MLton] using fold to write numeric constants
Stephen Weeks
MLton@mlton.org
Fri, 10 Feb 2006 10:08:18 -0800
> Looking briefly at the code, I noticed a minor simplification:
>
> > fun make (zero, op *, op +, op <, op <=, i2x, x2s) base =
> ^^^^ ^^^^^
>
> Only one of those is needed.
...
> The `zero' could also be eliminated easily.
...
> This would be a useful simplification (from the user's point-of-view) if the
> `make' function would not be local.
Good catches. It does make sense for "make" to be exported, so that
the code can be used for user-specified types.
--------------------------------------------------------------------------------
fun $ (a, f) = f a
fun curry f x y = f (x, y)
fun id x = x
fun pass x f = f x
structure Fold =
struct
val fold = pass
fun step0 h (a1, f) = fold (h a1, f)
fun step1 h $ x = step0 (curry h x) $
end
structure Num =
struct
fun N ty base = Fold.fold (ty base, fn (n, _) => n)
fun make (op *, op +, op <, i2x, x2s) base =
let
val zero = i2x 0
val base = i2x base
in
(zero, fn (i, n) =>
let
val i = i2x i
in
if not (i < zero) andalso i < base then
n * base + i
else
raise Fail (concat
["Num: ", x2s i,
" is not a valid digit in base ", x2s base])
end)
end
val i = make (op *, op +, op <, id, Int.toString)
val ii = make (op *, op +, op <, IntInf.fromInt, IntInf.toString)
val w = make (op *, op +, op <, Word.fromInt, Word.toString)
fun ` z = Fold.step1 (fn (i, (ac, step)) => (step (i, ac), step)) z
val a = 10
val b = 11
val c = 12
val d = 13
val e = 14
val f = 15
end
local
fun make x2s x = print (concat [x2s x, "\n"])
in
val pi = make Int.toString
val pii = make IntInf.toString
val pw = make Word.toString
end
local
open Num
in
val () = pi (N i 10 `1`2`3 $)
val () = pii (N ii 10 `1`2`3`4`5`6`7`8`9`0`1`2 $)
val () = pw (N w 16 `1`b $)
val () = pi (N i 12 `1`a $)
val () = pii (N ii 8 `2`3 $)
val () = pw (N w 2 `1`1`0 $)
end