From: Gerd Stolpmann <gerd@gerd-stolpmann.de>
To: Gregoire Sutre <sutre@eecs.berkeley.edu>, caml-list@inria.fr
Subject: Re: [Caml-list] Open class type definition ?
Date: Mon, 23 Apr 2001 20:21:56 +0200 [thread overview]
Message-ID: <01042321362504.02753@ice> (raw)
In-Reply-To: <3AE2538F.83A03652@eecs.berkeley.edu>
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
prev parent reply other threads:[~2001-04-24 7:11 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2001-04-22 3:44 Gregoire Sutre
2001-04-23 18:21 ` Gerd Stolpmann [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=01042321362504.02753@ice \
--to=gerd@gerd-stolpmann.de \
--cc=caml-list@inria.fr \
--cc=sutre@eecs.berkeley.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox