[MLton] Slightly simpler functional record update

Vesa Karvonen vesa.karvonen@cs.helsinki.fi
Thu, 11 Aug 2005 01:33:26 +0300


Thinking about the functional record update technique, a couple of things
occured to me. First of all, functional record update makes sense for
plain tuples (which are really a form of record in SML). Also, the `fruN'
(or the `makeSetterN') functions seem to be doing two separable things:
- perform a "functional tuple update", and
- convert from a record to a tuple and back.
Starting from `makeSetter3', I simplified it to `set3', which performs a
functional 3-tuple update:

  fun set3 f v (v1, v2, v3) =
      let
         datatype ('v1, 'v2, 'v3) t =
                  V1 of 'v1 | V2 of 'v2 | V3 of 'v3
         fun g h v =
             (case h v of V1 v1 => v1 | _ => v1,
              case h v of V2 v2 => v2 | _ => v2,
              case h v of V3 v3 => v3 | _ => v3)
      in
         f (g V1, g V2, g V3) v
      end

The `set3' function can be used like this:

  (1, 2, 3) >| set3#2 ~2 >| set3#1 ~1 >| set3#3 ~3

Then I wrote a `set' function for the record {a, b, c} using `set3':

  fun set f v {a = v1, b = v2, c = v3} =
      let
         fun r (v1, v2, v3) = {a = v1, b = v2, c = v3}
      in
         r (set3 (f o r) v (v1, v2, v3))
      end

The `set' function can be used, as usual, like this:

  {a=1, b=1, c=1} >| set#b ~2 >| set#a ~1 >| set#c ~3

This formulation is slightly simpler (meaning the implementation requires
slightly less code) than the one based on `fruN' (or `makeSetterN') functions.
In addition, the functional tuple update, `setN', operations can be useful
on their own.

I think that this formulation may also be a bit easier to understand, because
the conversions (tuple <-> record) and the tuple update are now separated (and
can be understood on their own). Also, there is no need to mention first class
(or rank-2) polymorphism.

-Vesa Karvonen