caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: "Till Varoquaux" <till.varoquaux@gmail.com>
To: skaller <skaller@users.sourceforge.net>
Cc: "David Teller" <David.Teller@univ-orleans.fr>,
	OCaml <caml-list@inria.fr>
Subject: Re: [Caml-list] Labelling trees
Date: Thu, 7 Jun 2007 16:26:46 +0200	[thread overview]
Message-ID: <9d3ec8300706070726o3ed62650ob73c832fdfa92617@mail.gmail.com> (raw)
In-Reply-To: <1181178046.6546.54.camel@rosella.wigram>

> This is indeed a nasty problem I have too. In theory, polymorphic
> variants with open recursion support what you want by making a new
> parametric term with a new case
>
>         `TYPE_ast of typ * 'ast
>
> and then closing the recursion. This is a covariant extension.
>
> The problem is that whilst this is relatively easy to encode
> for 1 parameter, it gets messy with 2 .. and if you have
> 15 or so as I do as well .. it's just easier to use a dummy
> type or magic .. neither of which is satisfactory.

Well... this is what type constraints make this slightly less messy:

module Gram =
  struct
    type 'cst binop = Add | Sub | Mul | Div
    type 'cst constant = Int of int | Float of float
    type 'cst expr =
      Cst of 'constant
      | Ident of 'ident
      | Call of ('expr * ('expr list))
      | Binop of ('binop * 'expr * 'expr)
      | Fundecl of (('ident list) * 'instr)
      constraint 'cst =
        < instr : 'instr; ident : 'ident; expr : 'expr; constant : 'constant;
          binop : 'binop; ..
        >
    type 'cst ident = string
    type 'cst instr =
      Let of ((('ident * 'expr) list) * 'instr)
      | Exp of 'expr
      | Assign of ('ident * 'expr)
      | If of ('expr * 'instr * 'instr)
      | Bloc of 'instr list
      constraint 'cst = < instr : 'instr; ident : 'ident; expr : 'expr; .. >
  end
type cst =
  < instr : instr; ident : ident; expr : expr; constant : constant;
    binop : binop
  >
  and binop =
  cst Gram.binop
  and constant =
  cst Gram.constant
  and expr =
  cst Gram.expr
  and ident =
  cst Gram.ident
  and instr =
  cst Gram.instr

is an example. It still gets very boring and administartive so you
might want to harness Camlp4 here [1]. This file was actually
generated from a source file like this:

gram{
 ident := string;
 constant:= Int int | Float float;
 expr :=
|Cst constant
| Ident ident
| Call expr,[expr]
| Binop binop,expr,expr
| Fundecl [ident],instr;
 binop := Add | Sub | Mul | Div ;
 instr :=
| Let [(ident,expr)],instr
| Exp expr
| Assign ident,expr
| If expr,instr,instr
| Bloc [instr]
}

In this case you do not need polymorphic variant since you could
always generate types like:

type cst =
  < instr : instr; ident : ident; expr : expr; constant : constant;
    binop : binop
  >
  and binop = cst Gram.binop
  and constant = cst Gram.constant
  and expr = edec*cst Gram.expr
  and ident = cst Gram.ident
  and instr = idec*cst Gram.instr

where `idec` and `edec` are the decorations you want to add on the
nodes for the instructions and the expressions respectively.

>
> Nor is the above encoding very nice, since it doesn't ensure
> each branch of the tree is labelled, instead it simply caches
> values where you chose, to speed up the functional calculation.

> You CAN solve this with a list or array mapping the physical
> term address to the type, with O(N) performance (YUK).
> You can't use a Map or Hashtbl because they require ordering,
> and Ocaml moves objects around so ordering on addresses isn't stable.

Hashtbl don't require ordering they require hashing. Anyways I'm
pretty sure both the functions `Pervasives.compare` and `Hashtbl.hash`
actually work on the representation of the data, not on its physical
address (that's why compare can fail on recursive values) . You can
use both Hashtables and Maps but you might aim for a weak data
structure to limit memory leaks.... BTW: for some akward reason
Weak.Hashtbl is not a hashtable.

>
> Double indirection works though: instead of terms, use an integer
> which Maps to a term .. you can then also Map the integer to
> your type. Of course .. this isn't statically safe.

Huh????

Till Varoquaux
[1] This camlp4 extension is in pre-pre-pre-alpha state. It can be
browsed online:
http://till.varoquaux.free.fr/projects/mini_js/OpenTrees.ml.html


  reply	other threads:[~2007-06-07 14:26 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-06-06 19:43 David Teller
2007-06-06 21:22 ` [Caml-list] " Christophe Raffalli
2007-06-07  1:00 ` skaller
2007-06-07 14:26   ` Till Varoquaux [this message]
2007-06-07 23:09     ` skaller
2007-06-08  9:52       ` Till Varoquaux
2007-06-08 10:32         ` skaller
2007-06-07 14:25 ` Christian Stork
2007-06-07 23:48 ` Jeremy Yallop

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9d3ec8300706070726o3ed62650ob73c832fdfa92617@mail.gmail.com \
    --to=till.varoquaux@gmail.com \
    --cc=David.Teller@univ-orleans.fr \
    --cc=caml-list@inria.fr \
    --cc=skaller@users.sourceforge.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).