Mind blown.

Let's just call this branch... hmm, I dunno, how about 'OCaml 5'?

Sorry for the noise.

On Wed, May 6, 2015 at 11:58 AM, Jeremy Yallop <yallop@gmail.com> wrote:
On 6 May 2015 at 10:50,  <oleg@okmij.org> wrote:
> Of course MetaOCaml serialization can be improved. What I'd like to
> stress is that you don't have to wait for the improvement. You can
> always, instead of
>         .<fun u ->  x>.
> write
>         .<fun u -> .~(mylift x)>.
> where
>         mylift : t -> t code
> is *your* function that does whatever _you_ like it to do at that
> particular type t (it should still produce something of the type (t
> code)).
>
> If some particular mylift functions turn out popular, they can be
> added to MetaOCaml, to save everyone trouble writing them.
>
> And I generally agree with Leo that this implicit lifting is
> baroque. At present I'm not sure if requiring the explicit lifting is
> too much of a burden. I'm sure that with modular implicits, it won't
> be.

I've just pushed an OPAM switch for an OCaml compiler that combines
the MetaOCaml and modular implicits patches, making it possible to
experiment with explicit user-defined polymorphic CSP.

For example, you might define a signature, CSP, for "things that can
be persisted":

  module type CSP =
   sig
     type t
     val lift : t -> t code
  end

together with a top-level function that dispatches to the appropriate instance

  let csp (implicit C: CSP) (x : C.t) = C.lift x

and instances of CSP for each type of interest.  Here's an instance
for the stx type from earlier in the thread:

  implicit module CSP_stx : CSP with type t = stx =
  struct
    type t = stx

    let rec lift : stx -> stx code = function
      | A -> .< A >.
      | B s -> .< B .~ (lift s) >.
      | C (s1, s2) -> .< C ( .~(lift s1), .~(lift s2) ) >.
   end

and here's a parameterised instance for lists that makes it possible
to persist lists of any persistable element type:

  implicit functor CSP_list(C: CSP) : CSP with type t = C.t list =
  struct
    type t = C.t list

    let rec lift : C.t list -> C.t list code = function
        [] -> .< [] >.
      | x :: xs -> .< .~(csp x) :: .~(lift xs) >.
  end

These two instances make it possible to use the CSP function to
persist stx values, or lists of stx values, or lists of lists of stx
values (etc.):

   # let ba = B A in .< .~(csp ba) >.;;
   - : stx code = .<Stx.B Stx.A>.

  # let l = [A; B A] in .< .~(csp l) >.;;
  - : stx list code = .<[Stx.A; Stx.B Stx.A]>.

  # let ll = [[A; B A]] and ba = B A in .< .~(csp ll), .~(csp ba) >.;;
  - : (stx list list * stx) code = .<([[Stx.A; Stx.B Stx.A]], (Stx.B Stx.A))>.

It's easy to imagine having the csp function built in to MetaOCaml, so
that we could write .< x >.  (or some similarly convenient syntax) to
mean .< .~(csp x) >...

You can try out the switch with OPAM in the usual way:

   opam update
   opam switch 4.02.1+modular-implicits-ber
   eval `opam config env`

Jeremy.

--
Caml-list mailing list.  Subscription management and archives:
https://sympa.inria.fr/sympa/arc/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs