[MLton] Slightly simpler functional record update

Stephen Weeks MLton@mlton.org
Fri, 12 Aug 2005 09:48:00 -0700


> in the definition of set complicated enough to be worth abstracting
> into a makeSetter3 function.  I like separating the update from the
> conversions, but I think it makes the isomorphism clearer to define
> the set function via makeSetter3 as follows.
> 
> ----------------------------------------------------------------------
> fun makeSetter3 (r1, r2, t) f z s = r1 (set3 (f o r2) z (t s))

It occurs to me that there is nothing specific to 3-tuples in the
concept of converting a tuple-setter into a record-setter.  So, we
could use a generic wrapSet as follows.

----------------------------------------------------------------------

fun wrapSet (set, r1, r2, t) f z s = r1 (set (f o r2) z (t s))

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

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

fun set f =
   let
      fun r (a, b) = {a = a, b = b}
      fun t {a, b} = (a, b)
   in
      wrapSet (set2, r, r, t) f
   end

val r = {a=1, b=1} >| set#b ~2 >| set#a ~1
   
fun set f =
   let
      fun r (a, b, c) = {a = a, b = b, c = c}
      fun t {a, b, c} = (a, b, c)
   in
      wrapSet (set3, r, r, t) f
   end

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