tabulators

Matthew Fluet Matthew Fluet <fluet@CS.Cornell.EDU>
Thu, 24 Jan 2002 23:44:33 -0500 (EST)


> As you showed, it is easy to convert from iterate to fold, just as it
> is easy to convert from construct to unfold.

This initially struck me as surprising; arguing by duals would seem to
suggest the opposite.

Although, it's not that hard to go from a fold to an iterate:

functor FtoI (S: FOLD): ITERATE =
   struct
      type 'a t = 'a S.t
      datatype 'a iter = Iter of unit -> ('a * 'a iter) option

      fun iterate v =
	 (S.fold (v, fn e => e, fn (x, b) =>
		  fn e => b (Iter (fn () => SOME (x, e)))))
	 (Iter (fn () => NONE))
   end

So, why is it so hard to go from an unfold to a construct? 
Maybe it's not that hard:

functor UtoC (S: UNFOLD): CONSTRUCT =
   struct
      type 'a t = 'a S.t
      datatype 'a cons = Done of 'a t | More of 'a -> 'a cons

      fun construct n =
	 let
	    datatype 'a u = U of unit -> 'a * 'a u
	    val error = U (fn () => raise Fail "UtoC")
	    fun mkCons (i, b) =
	       if i >= n
		  then Done (S.unfold (n, b error, fn U f => f ()))
	       else More (fn x => mkCons (i + 1, fn e => 
					  b (U (fn () => (x, e)))))
	 in
	    mkCons (0, fn e => e)
	 end
   end

> signature ITERATE2 =
>    sig
>       type 'a t
>       type 'a state
>       val iterate: 'a t -> {next: 'a state -> ('a * 'a state) option,
> 			      start: 'a state}
>    end

I still don't get why this (or CONSTRUCT2) is useful?  If you build it up
using C7to2, then you don't seem to have any choice in the state.