* [Caml-list] Open class type definition ?
@ 2001-04-22 3:44 Gregoire Sutre
2001-04-23 18:21 ` Gerd Stolpmann
0 siblings, 1 reply; 2+ messages in thread
From: Gregoire Sutre @ 2001-04-22 3:44 UTC (permalink / raw)
To: caml-list
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 would ensure that the type t has a to_string() method, and then I could
have the following functor:
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
where I could use to_string().
The problem is that the declaration for type t above:
type t = < to_string : unit -> string >
actually enforces objects to have only the to_string method and no other
public methods. But the compare function may need to read the contents of
the objects, and for that it would need public accessors. Consider for
instance the following module:
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 >
So I tried to define the type t in the signature so that it does not enforce
objects to have only the to_string method. I tried the following open type:
type t = < to_string : unit -> string; .. >
but I get the error:
Unbound type parameter <..>
I also tried the # construct, without success:
# class type class_t = object val to_string : unit -> string end;;
class type class_t = object val to_string : unit -> string end
# type t = #class_t;;
Unbound row variable in
#class_t
Is it possible to define such open class types. And if not then why is it
so ?
Greg.
--
Gregoire Sutre 144MB Cory Hall
sutre@eecs.berkeley.edu University of California
Phone: (510) 643-2801 Berkeley, CA 94720
-------------------
To unsubscribe, mail caml-list-request@inria.fr. Archives: http://caml.inria.fr
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [Caml-list] Open class type definition ?
2001-04-22 3:44 [Caml-list] Open class type definition ? Gregoire Sutre
@ 2001-04-23 18:21 ` Gerd Stolpmann
0 siblings, 0 replies; 2+ messages in thread
From: Gerd Stolpmann @ 2001-04-23 18:21 UTC (permalink / raw)
To: Gregoire Sutre, caml-list
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
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2001-04-24 7:11 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-04-22 3:44 [Caml-list] Open class type definition ? Gregoire Sutre
2001-04-23 18:21 ` Gerd Stolpmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox