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
next prev parent 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