[MLton-user] 
	Generating dummy values for tying cycles, serialization
    Vesa Karvonen 
    vesa.karvonen at cs.helsinki.fi
       
    Mon Aug 28 22:50:13 PDT 2006
    
    
  
In
  Type-Specialized Serialization with Sharing,
  Martin Elsman,
  University of Copenhagen,
  IT University Technical Report TR-2004-43, 2004.
  http://mlton.org/References#Elsman04
a type-indexed serialization library is described that has a combinator
refCyc for serializing (possibly cyclic) references.  refCyc has the
specification
  val refCyc : 'a -> 'a pu -> 'a ref pu
which means that the user is responsible for passing a dummy value (the
first parameter) to refCyc for tying cycles.  (Read the report for further
details.)  In this very brief note (few words, more code) I'll show how to
generate dummy type-indexed values.
(The end of this message contains some utilities.  Full code is included
in this message.)
First a generic signature for "structural" type-indexed values:
signature STRUCTURAL_TYPE =
   sig
      type 'a t
      val iso : ('a, 'b) emb -> 'b t -> 'a t
      val * : 'a t * 'b t -> ('a, 'b) product t
      val + : 'a t * 'b t -> ('a, 'b) sum t
      val Y : 'a t Fix.t
      val --> : 'a t * 'b t -> ('a -> 'b) t
      val exn : exn t
      val regExn : (exn -> ('a * 'a t) option) effect
      val array : 'a t -> 'a array t
      val list : 'a t -> 'a list t
      val refc : 'a t -> 'a ref t
      val vector : 'a t -> 'a vector t
      val bool : bool t
      val char : char t
      val int : int t
      val real : real t
      val string : string t
      val unit : unit t
      val word : word t
   end
Then the signature for the type-indexed dummy values:
signature DUMMY =
   sig
      include STRUCTURAL_TYPE
      val dummy : 'a t -> 'a
      val prj : ('b -> 'a) -> 'b t -> 'a t
   end
The implementation is mostly straightforward (see the comments for some
fine points):
structure Dummy :> DUMMY =
   struct
      type 'a t = 'a option
      val dummy = valOf
      fun prj b2a = Option.map b2a
      fun iso (_, p) = prj p
      (* When computing dummy products and sums we propagate definedness: *)
      fun a * b = case a & b of
                     SOME a & SOME b => SOME (a & b)
                   | _ => NONE
      fun a + b = case a of
                     SOME a => SOME (INL a)
                   | NONE => Option.map INR b
      fun Y ? = Fix.pure (const (NONE, id)) ?
      (* We use the more general Fixpoint framework (by Stephen Weeks)
       * that allows functional fixpoints.  Note that the initial value is
       * undefined.
       *)
      fun _ --> _ = SOME (fail (Fail "Dummy.-->"))
      (* To define a function (for example), no other dummy values are
       * needed.
       *)
      val exn = SOME Empty
      val regExn = ignore
      fun array _ = SOME (Array.tabulate (0, undefined))
      fun list _ = SOME []
      fun refc a = Option.map ref a
      fun vector _ = SOME (Vector.tabulate (0, undefined))
      val bool = SOME false
      val char = SOME #"\000"
      val int = SOME 1
      val real = SOME 0.0
      val string = SOME ""
      val unit = SOME ()
      val word = SOME 0w0
   end
Here is an example:
datatype 'a tree = B of 'a tree * 'a * 'a tree | N
fun tree a =
    let
       open Fix Dummy
    in
       fix Y (fn tree_a =>
                 iso (fn B (l, x, r) => INL (l & x & r) | N => INR (),
                      fn INL (l & x & r) => B (l, x, r) | INR () => N)
                     (tree_a * a * tree_a + unit))
    end
val N =
    let
       open Dummy
    in
       dummy (tree int)
    end
Using this technique, it should be possible to build a serialization
library that doesn't require the user to specify a dummy value for
serializing references.
The necessary utilities and the Fixpoint framework are below.
-Vesa Karvonen
(* Operator precedence table *)
infix   8  * / div mod        (* +1 from Basis Library *)
infix   7  + - ^              (* +1 from Basis Library *)
infixr  6  :: @               (* +1 from Basis Library *)
infix   5  = <> > >= < <=     (* +1 from Basis Library *)
infix   4  <\ \>
infixr  4  </ />
infix   3  o
infix   2  >|
infixr  2  |<
infix   1  :=                 (* -2 from Basis Library *)
infix   0  before &
infixr  0  -->
(* Some basic combinators *)
fun const x _ = x
fun cross (f, g) (x, y) = (f x, g y)
fun curry f x y = f (x, y)
fun fail e _ = raise e
fun id x = x
fun undefined _ = raise Fail "undefined"
fun fst (a, _) = a
fun snd (_, b) = b
(* Product type *)
datatype ('a, 'b) product = & of 'a * 'b
(* Sum type *)
datatype ('a, 'b) sum = INL of 'a | INR of 'b
(* Some type shorthands *)
type 'a sq = 'a * 'a
type 'a uop = 'a -> 'a
type 'a fix = 'a uop -> 'a
type 'a thunk = unit -> 'a
type 'a effect = 'a -> unit
type 'a compare = 'a sq -> order
type ('a, 'b) emb = ('a -> 'b) * ('b -> 'a)
(* Infixing, sectioning, and application operators *)
fun x <\ f = fn y => f (x, y)
fun f \> y = f y
fun f /> y = fn x => f (x, y)
fun x </ f = f x
(* Piping operators *)
val op>| = op</
val op|< = op\>
(* Fixpoint framework with the "pure" combinator *)
signature FIX =
   sig
      type 'a t1
      type 'a t2
      type 'a t = 'a t1 -> 'a t2
      exception Fix
      val fix : 'a t -> 'a fix
      val pure : ('a * 'a uop) thunk -> 'a t
      val tier : ('a * 'a effect) thunk -> 'a t
      val iso : ('a, 'b) emb -> 'b t -> 'a t
      val ^ : 'a t * 'b t -> ('a, 'b) product t
   end
structure Fix :> FIX =
   struct
      type 'a t1 = unit
      type 'a t2 = 'a * 'a uop
      type 'a t = 'a t1 -> 'a t2
      exception Fix
      fun fix a f =
         let
            val (a, ta) = a ()
         in
            ta (f a)
         end
      val pure = id
      fun tier th () =
          let
             val (a, ta) = th ()
          in
             (a, const a o ta)
          end
      fun iso (a2b, b2a) b () =
         let
            val (b, tb) = b ()
         in
            (b2a b, b2a o tb o a2b)
         end
      fun (a ^ b) () =
         let
            val (a, ta) = a ()
            val (b, tb) = b ()
         in
            (a & b, fn a & b => ta a & tb b)
         end
   end
    
    
More information about the MLton-user
mailing list