Now it looks super nice!
Thanks a lot Jeremy, your explanations were really helpful!
ph.
On 5 January 2013 13:40, Philippe Veber <philippe.veber@gmail.com> wrote:It's analogous to '_' in patterns: a kind of anonymous type variable
> I still have a question though: what is the exact meaning of the _
> character in the polymorphic type "< rn : 'a. int * 'a expr -> _>"
> and how is it useful/necessary for your example to run?
that you can use to avoid giving a name to a type. (As with "_" in
patterns, there"s no connection between occurrences of "_", so "_ *
int -> _" means "'a * int -> 'b", not "'a * int -> 'a", for example.)
It's not doing anything special here: you could equally give a name to
the type without changing the meaning of the code.
I don't believe it's possible to make function arguments polymorphic
> Could your example be written without a record/object type using
> polymorphic type annotations for functions?
using annotations. However, the code can be significantly simplified
to remove that bit of polymorphism altogether. As written it mixes
two techniques for hiding the type index in the expression GADT during
parsing: CPS (in the inner 'parse' function) and an existential type
(in the return type of 'parse_expr'). In fact, either of these
approaches in isolation is sufficient. Here's a more direct
implementation using only the existential:
(* Well-typed parser. Incomplete -- it doesn't handle fst and snd -- and a
bit careless about error-checking. Perhaps sufficient to give a flavour.let rec parse s pos =
*)
let parse_expr : string -> any_expr =
match s.[pos] with
| 'T' -> pos + 1, Expr True
| 'F' -> pos + 1, Expr False
| '!' -> let pos', Expr e = parse s (pos + 1) in
(* Check that 'e' has boolean type before we can parse it tobegin match type_of e with
Not. This is more than just good practice: without the
type-checking step the parser won't compile. *)
| TBool -> pos', Expr (Not e)
| t -> typing_failure (pos + 1) pos' s TBool t| '(' -> let pos, Expr l = parse s (pos + 1) in
end
if s.[pos] <> ',' then parsing_failure pos ',' s elselet pos, Expr r = parse s (pos + 1) in
if s.[pos] <> ')' then parsing_failure pos ')' s elsepos + 1, Expr (Pair (l, r))
in
fun s -> snd (parse s 0)