[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: | 2001-04-24 (07:11) |
From: | Gerd Stolpmann <gerd@g...> |
Subject: | Re: [Caml-list] Open class type definition ? |
On Sun, 22 Apr 2001, Gregoire Sutre wrote: >Hi, > >I'm trying to use the Object model of OCaml and I'm having trouble with the >class types. > >My goal is to have datatypes that can be easily converted into strings for >debugging purposes. So instead of enclosing each datatype inside a >dedicated module with a to-string() function (that would lead to a huge >number of modules), I thought that I could use an object type instead, >saying that there is *at least* a method to_string(), and define my >datatypes as classes with *at least* a to_string() method inside each class. > >For instance, I could specify an ordered type this way: > >module type ORDERED_TYPE = > sig > type t = < to_string : unit -> string > > val compare : t -> t -> int > end This module type is already problematic. The O'Caml types are very strict, and this definition of 'compare' means that the function can only call the to_string method, and nothing more. [...] >module Funct(A : ORDERED_TYPE) = > struct > let display_cmp x y = x#to_string() ^ " cmp " ^ x#to_string() ^ > " = " ^ (string_of_int (A.compare x y)) > end [...] > >module Foo = > struct > class my_int x = > object > val mutable v = x > method to_string () = "Int(" ^ (string_of_int v) ^")" > method get_v = v > method set_v new_v = v <- new_v > end > > type t = my_int > let compare (x:t) (y:t) = compare x#get_v y#get_v > end > >In this module, the compare function reads the integer value stored in the >objects to perform its job. But then, the type t of the Foo module does not >correspond to the type t of the ORDERED_TYPE signature and I can not apply >the functor to Foo: > >[...] >Type declarations do not match: > type t = my_int >is not included in > type t = < to_string : unit -> string > The problem is that subtyping is not allowed when the compiler checks whether an implementation matches a signature. (Can somebody of the experts explain this?) Declaring t with an ellipsis ("..") does change nothing, because even if the compiler accepted t = to_string : unit -> string; ..> it would be still necessary that the subtyping relation t :> my_int holds. So the consequences for program design are: - Use classes when subclassing and/or subtyping is needed - Use functors when information hiding is more important - Do not mix both concepts in the sense that applying a functor bases on a subtyping relation The possible solutions for your concrete problem: (1) Prefer classes: module type ORDERED_TYPE = sig class type t = object method to_string : unit -> string method compare : t -> int end end (2) Accept that the class t is only a "vehicle" for a certain effect, and make the method get_v accessible: module type ORDERED_TYPE = sig class type ['a] t = object method to_string : unit -> string method get_v : 'a end end (3) Consider also the following solution without classes: (similar to (2)) module type ORDERED_TYPE = sig type t_base type t = { to_string : unit -> string; v : t_base } val compare : t -> t -> int end module Foo = struct type t_base = int type t = { to_string : unit -> string; v : t_base } let make n = { to_string = (fun () -> "Int(" ^ string_of_int n ^ ")"); v = n; } let compare (x:t) (y:t) = compare x.v y.v end module Funct(A : ORDERED_TYPE) = struct let display_cmp x y = x.A.to_string() ^ " cmp " ^ y.A.to_string() ^ " = " ^ (string_of_int (A.compare x y)) end I have also a fourth solution, but I do not recommend it: Misuse polymorphic variants to tag the type explicitly, and use a central to_string like let to_string x = match Obj.magic x with `Int n -> Int(" ^ string_of_int n ^ ")" | ... other cases ... This is unsafe, and you will get segfaults if type passed to to_string is not any of the enumerated variants. Gerd -- ---------------------------------------------------------------------------- Gerd Stolpmann Telefon: +49 6151 997705 (privat) Viktoriastr. 100 64293 Darmstadt EMail: gerd@gerd-stolpmann.de Germany ---------------------------------------------------------------------------- ------------------- To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr