[
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: | -- (:) |
| 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