Version française
Home     About     Download     Resources     Contact us    
Browse thread
[Caml-list] Fwd: Polymorphic optional label argument, with default
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Jacques Garrigue <garrigue@k...>
Subject: Re: [Caml-list] Fwd: Polymorphic optional label argument, with default
From: Richard Jones <rich@annexia.org>
> On Sun, Apr 11, 2004 at 01:26:24AM -0500, Brian Hurt wrote:
> > >   plot : ?labels : ('a -> string) -> (* ... 'a ... *) -> unit
> > > 
> > > [The 'a types are the same type.  If I leave out the initializer, then
> > > it works.]
> > 
> > I don't think it's possible.  Consider the following situation: I pass in 
> > a graph of floats for example, and then forget to specify a labels 
> > argument.  Now you're passing a float to string_of_int.
> 
> I'd want this to generate a compile-time error, because the 'a 's
> aren't the same.
> 
> It's perfectly possible to define this function if one leaves out the
> default argument, or sets the default argument to a function typed as
> 'a -> string.
> 
> # let plot ~labels graph = print_endline (labels graph);;
> val plot : labels:('a -> string) -> 'a -> unit = <fun>
> 
> or:
> 
> # let string_of_any x = "foo";;
> val string_of_any : 'a -> string = <fun>
> # let plot ?(labels = string_of_any) graph = print_endline (labels graph);;
> val plot : ?labels:('a -> string) -> 'a -> unit = <fun>
> 
> But not if I want the default to be the most common case (which is
> that my graph will be a graph of ints).  I want the common case in
> there so that most of the time end users of the API won't need to
> worry about ~labels and optional arguments.

What you are asking for has already been discussed on this list, a few
years ago. Here is my answer at that time:
  http://caml.inria.fr/archives/200102/msg00212.html

Basically, what you are asking for is a new type of constraint, which
is only to be applied when the optional argument is omitted (and as
result the default is selected).
This is not possible in the current type system, and while there are
some uses for that, it would be hard to justify making types more
complex in the general case, just to handle this specific problem.

Note that there is an encoding, which does not provide optional
arguments, but just a way to handle this kind of default in an
explicit way.

module Opt : sig
  type ('a,'b) t
  val omit : ('a,'a) t
  val arg : 'a -> ('a,'b) t
  val get : default:'b -> ('a,'b) t -> 'a
end = struct
  type ('a,'b) opt = Omit | Arg of 'a
  let omit = Omit
  let arg x = Arg x
  let get ~default = function
      Omit -> Obj.magic default
    | Arg x -> x
end

Note that the typing makes this use of Obj.magic OK.

Then your function may be defined to take as argument either Opt.omit
or (Opt.arg f).

This probably doesn't solve your problem, but this may help you to see
the issues involved.

Jacques Garrigue

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners