Hi Richard,

Note that you can still write < hello: string; .. > in the signature of
register_obj and do the cast before adding your object to the list:

  let register_obj name obj = objs := (name, (obj :> < hello: string >)) :: !objs

This way you do not need to downcast at each call-site of register_obj.

Cheers,
Nicolas



On Wed, Feb 22, 2017 at 6:36 PM, Richard W.M. Jones <rich@annexia.org> wrote:
On Wed, Feb 22, 2017 at 12:09:37PM -0500, Gabriel Scherer wrote:
> The signature you demand is actually incorrect, because the return
> type of get_obj is to permissive: it claims that it can return *any*
> ('a obj), so you could register an object with just the hello method
> and get back an object with more methods.
>
> On the other hand, if you use the monomorphic < hello : string > type
> in the interface, then it is type-correct and the implementation you
> provide is accepted. It is explicit in the fact that you can't recover
> the extra methods of the object once they have been stored in this
> lowest-common-denominator container.

Ah, I see.

Modifying the code to use the monomorphic type works, but I have to
downcast the objects to the right type.  For reference, the working
code is below.

Thanks,

Rich.

list_fns.mli --------------------------------------------------------
type obj = < hello : string >
val register_obj : string -> obj -> unit
val get_obj : string -> obj

list_fns.ml ---------------------------------------------------------
type obj = < hello : string >
let objs = ref []
let register_obj name obj = objs := (name, obj) :: !objs
let get_obj name = List.assoc name !objs

test.ml -------------------------------------------------------------
class foo = object
  method hello = "hello from foo"
  method goodbye () = print_endline "goodbye"
end

class bar = object
  method hello = "hello from bar"
end

let () =
  let o1 = new foo in
  let o2 = new bar in
  List_fns.register_obj "o1" (o1 :> List_fns.obj);
  List_fns.register_obj "o2" (o2 :> List_fns.obj);
  print_endline ("calling o1: " ^ (List_fns.get_obj "o1")#hello);
  print_endline ("calling o2: " ^ (List_fns.get_obj "o2")#hello)
--------------------------------------------------------------------

--
Caml-list mailing list.  Subscription management and archives:
https://sympa.inria.fr/sympa/arc/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs