Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Caml-list] format polymorphism

2 views
Skip to first unread message

Christophe TROESTLER

unread,
Aug 6, 2006, 7:51:39 PM8/6/06
to O'Caml Mailing List
Hi,

Could someone tell me why, say "%s", is of type

'a. (string -> 'b, 'a, 'b) format

instead of

'a 'b. (string -> 'b, 'a, 'b) format

I am asking this because if one wants to use the same format string
both for reading and printing in a given function, one needs the
latter type:

type 'a fmt = { fmt: 'b 'c. ('a,'b,'c) format }
fun (s: _ fmt) -> Printf.printf s.fmt, Scanf.sscanf "string" s.fm

However, I cannot instantiate the type [_ fmt]. This is in contrast
with

let s = ("%s": (_,_,_) format) in
Printf.printf s, Scanf.sscanf "string" s

which works as intended. I think this may have been discussed before;
I just can't remember the reason. Also, is there a safe way of using
Obj.magic to make it work ?

Regards,
ChriS

_______________________________________________
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

Jacques Garrigue

unread,
Aug 9, 2006, 3:51:40 AM8/9/06
to Christophe...@umh.ac.be
From: Christophe TROESTLER <Christophe...@umh.ac.be>

> Could someone tell me why, say "%s", is of type
>
> 'a. (string -> 'b, 'a, 'b) format
>
> instead of
>
> 'a 'b. (string -> 'b, 'a, 'b) format

It clearly has the second type!

> I am asking this because if one wants to use the same format string
> both for reading and printing in a given function, one needs the
> latter type:
>
> type 'a fmt = { fmt: 'b 'c. ('a,'b,'c) format }
> fun (s: _ fmt) -> Printf.printf s.fmt, Scanf.sscanf "string" s.fm

With your definition of fmt, you are requiring 'c to be independent
from 'a. But If you look at the type of "%s", you see that
'a = string -> 'c, so that {fmt="%s"} is not well-typed.

A solution is to define it as
type 'a fmt = {fmt: 'b 'c. ('a -> 'b, 'c, 'b) format}

The drawback is that only allows formats taking one argument.
One could add definitions for any defined number of arguments, but I
don't see any generic solution.

Cheers,

Jacques Garrigue

Christophe TROESTLER

unread,
Aug 9, 2006, 6:56:52 PM8/9/06
to garr...@math.nagoya-u.ac.jp
On Wed, 09 Aug 2006, Jacques Garrigue <garr...@math.nagoya-u.ac.jp> wrote:
>
> > 'a 'b. (string -> 'b, 'a, 'b) format
>
> It clearly has the second type!

Thanks for answering -- I got badly confused by the error message !
(shame on me :)

> > type 'a fmt = { fmt: 'b 'c. ('a,'b,'c) format }
> > fun (s: _ fmt) -> Printf.printf s.fmt, Scanf.sscanf "string" s.fm
>
> With your definition of fmt, you are requiring 'c to be independent
> from 'a. But If you look at the type of "%s", you see that
> 'a = string -> 'c, so that {fmt="%s"} is not well-typed.

Well, yes, of course, that's obvious after you stated it! :)

> A solution is to define it as
> type 'a fmt = {fmt: 'b 'c. ('a -> 'b, 'c, 'b) format}
>
> The drawback is that only allows formats taking one argument.
> One could add definitions for any defined number of arguments, but I
> don't see any generic solution.

Yeah but I really want to allow as many arguments as the user desires.
That's a bit of an annoyance for printf/scanf like schemes: you have
to know in advance in how many contexts you may want to simultaneously
use an argument of type format in order to put enough type parameters...

So I suppose my best luck to do it cleanly is to use camlp4 to make
the parameter duplication for the user. Another approach I was
thinking about is to define a new type, say

type ('a,'b,'c,'d) fmt

and have (for the above application)

external pr_fmt : (_, _, 'a, 'c) fmt -> ('a, out_channel, 'c) format = "%identity"
external sc_fmt : ('a, 'c, _, _) fmt -> ('a, Scanf.Scanning.scanbuf, 'c) format = "%identity"
external ( !/ ) : ('a, _, 'b) format -> ('a, 'b, 'a, _) fmt = "%identity"

let f s =
Printf.printf (pr_fmt s), Scanf.sscanf "string" (sc_fmt s)

f !/"%s %u"

Now, of course ( !/ ) is not completely doing what I want. If
[pr_fmt] and [sc_fmt] are for purely internal use by the library --
thus user only seeing [/!] -- is the above safe? Is there a way using
Camlp4 to reinterpret a string in the new type (possibly prefixing it
with !/ or another chosen symbol to distinguish it) so that,
say, !/"%i %f" becomes (Obj.magic "%i ... %f": (int -> float -> 'a,
'a, int -> float -> 'b, 'b) fmt) ?

Thanks for your help,
ChriS


P.S. Out of curiosity, is there a type system with inference (say,
extending the one of OCaml) that can handle this kind of thing cleanly?

0 new messages