* [Caml-list] functors and objects
@ 2004-02-03 18:06 Damien
2004-02-03 19:37 ` Matt Gushee
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Damien @ 2004-02-03 18:06 UTC (permalink / raw)
To: caml-list
Hello,
I would like to write something like
<<
class type o =
object
method react: unit
end
module type O =
sig
type t :> o (* sigh... *)
end
module R(M: O) =
struct
let l: M.t list ref = []
let register (o: M.t) = l := o :: !l
let react() = List.iter (fun o -> o#react) !l
end
>>
and then, in a second layer, something like
<<
class type o' =
object
inherit o
method render: unit
end
module type O' =
sig
type t :> o'
end
module R(M: O') =
struct
include R(M)
let render() = List.iter (fun o -> o#render) !l
end
>>
I tried all sort of tricks with #o, type 'a t = #o as 'a ...
but I didn't managed to to it :(
(without turning my objects into plain modules)
Any idea ?
Is it unsound to let a functor use an object type ?
(not to inherit from the class,
just to use the methods of objects belonging to this type)
thanks,
damien
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] functors and objects
2004-02-03 18:06 [Caml-list] functors and objects Damien
@ 2004-02-03 19:37 ` Matt Gushee
2004-02-03 19:39 ` [Caml-list] functors and objects' Matt Gushee
2004-02-04 2:57 ` [Caml-list] functors and objects Jacques Garrigue
2 siblings, 0 replies; 9+ messages in thread
From: Matt Gushee @ 2004-02-03 19:37 UTC (permalink / raw)
To: caml-list
On Tue, Feb 03, 2004 at 07:06:35PM +0100, Damien wrote:
>
> I would like to write something like
>
> <<
> class type o =
> object
> method react: unit
> end
>
> module type O =
> sig
> type t :> o (* sigh... *)
> end
The first problem is that you're mixing type declarations and class
casts ... not a hard mistake to make, since the class cast syntax is a
bit confusing, and doesn't seem to be explained very well anywhere.
Anyway, you seem to have missed the simplest solution:
module type O =
sig
type t = o
end
> module R(M: O') =
> struct
> include R(M)
I don't see how this can work, because this module R takes an argument
of type O', whereas the other R (do you really want to give them the
same name?) takes an argument of type O. Regardless of their contents,
they are different interfaces and thus not interchangeable. There's
undoubtedly a way to achieve the result you want, but I don't really
understand what you are trying to do. Do you actually have a specific
goal in mind, or are you just experimenting?
--
Matt Gushee When a nation follows the Way,
Englewood, Colorado, USA Horses bear manure through
mgushee@havenrock.com its fields;
http://www.havenrock.com/ When a nation ignores the Way,
Horses bear soldiers through
its streets.
--Lao Tzu (Peter Merel, trans.)
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] functors and objects'
2004-02-03 18:06 [Caml-list] functors and objects Damien
2004-02-03 19:37 ` Matt Gushee
@ 2004-02-03 19:39 ` Matt Gushee
2004-02-03 20:26 ` Damien Pous
2004-02-04 2:57 ` [Caml-list] functors and objects Jacques Garrigue
2 siblings, 1 reply; 9+ messages in thread
From: Matt Gushee @ 2004-02-03 19:39 UTC (permalink / raw)
To: caml-list
On Tue, Feb 03, 2004 at 07:06:35PM +0100, Damien wrote:
>
> I would like to write something like
>
> <<
> class type o =
> object
> method react: unit
> end
>
> module type O =
> sig
> type t :> o (* sigh... *)
> end
The first problem is that you're mixing type declarations and class
casts ... not a hard mistake to make, since the class cast syntax is a
bit confusing, and doesn't seem to be explained very well anywhere.
Anyway, you seem to have missed the simplest solution:
module type O =
sig
type t = o
end
> module R(M: O') =
> struct
> include R(M)
I don't see how this can work, because this module R takes an argument
of type O', whereas the other R (do you really want to give them the
same name?) takes an argument of type O. Regardless of their contents,
they are different interfaces and thus not interchangeable. There's
undoubtedly a way to achieve the result you want, but I don't really
understand what you are trying to do. Do you actually have a specific
goal in mind, or are you just experimenting?
--
Matt Gushee When a nation follows the Way,
Englewood, Colorado, USA Horses bear manure through
mgushee@havenrock.com its fields;
http://www.havenrock.com/ When a nation ignores the Way,
Horses bear soldiers through
its streets.
--Lao Tzu (Peter Merel, trans.)
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] functors and objects'
2004-02-03 19:39 ` [Caml-list] functors and objects' Matt Gushee
@ 2004-02-03 20:26 ` Damien Pous
0 siblings, 0 replies; 9+ messages in thread
From: Damien Pous @ 2004-02-03 20:26 UTC (permalink / raw)
To: caml-list
En réponse à Matt Gushee <mgushee@havenrock.com>:
> On Tue, Feb 03, 2004 at 07:06:35PM +0100, Damien wrote:
> > type t :> o (* sigh... *)
>
> The first problem is that you're mixing type declarations and class
> casts ... not a hard mistake to make, since the class cast syntax is a
> bit confusing, and doesn't seem to be explained very well anywhere.
of course, this was not "real OCaml code" :)
I just wanted to express the fact that my functor R has to accept any module M
defining an object type `t' with at least a method `react'
(that is, t :> o)
> > module R(M: O') =
> > struct
> > include R(M)
>
> I don't see how this can work, because this module R takes an argument
> of type O', whereas the other R (do you really want to give them the
> same name?) takes an argument of type O. Regardless of their contents,
> they are different interfaces and thus not interchangeable.
since o' :> o, M: O' should be a valid candidate for R...
> There's undoubtedly a way to achieve the result you want, but I don't
> really understand what you are trying to do.
the following correct code does partially what I want :
module type O = sig
type t
val send: [<`React] -> t -> unit
end
module R(M: O) = struct
let l = ref []
let register (o: M.t) = l := o :: !l
let react() = List.iter (M.send `React) !l
end
module type O' = sig
type t
val send: [<`React|`Render] -> t -> unit
end
module R'(M: O') = struct
include R(M) (* <-- "subtyping" is automagically done *)
let render() = List.iter (M.send `Render) !l
end
but I am partially re-encoding objects with modules and variants,
and this encoding becomes quite ugly when it comes to _real_ objects
(with inheritance, virtual methods...)
> Do you actually have a specific goal in mind, or are you just experimenting?
both !
I am working on a project that use a "Reactor" where a lots of "Objects" react.
This project is cut into three layers :
Base reactor and objects (generic)
Meaningful reactor and objects (objects really react)
Rendered reactor and objects (Gtk, maybe GL some day)
Currently both reactor and objects are "OCaml objects", but the project only use
_one_ instance of the rendered reactor class. Thus I am wondering how I could
turn it into a module...
This module has to be defined incrementally : Base, Meaningful, Rendered.
but at the Base level, the final type of contained objects is unknown,
whence the need for a functor.
(with objects, this is done with parametrized classes)
Since objects really need to be "objects" (late binding),
I cannot turn both objects and reactor into modules (or at least in a beautiful way)
arf...
damien
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] functors and objects
2004-02-03 18:06 [Caml-list] functors and objects Damien
2004-02-03 19:37 ` Matt Gushee
2004-02-03 19:39 ` [Caml-list] functors and objects' Matt Gushee
@ 2004-02-04 2:57 ` Jacques Garrigue
2004-02-05 8:55 ` Damien
2 siblings, 1 reply; 9+ messages in thread
From: Jacques Garrigue @ 2004-02-04 2:57 UTC (permalink / raw)
To: Damien.Pous; +Cc: caml-list
From: Damien <Damien.Pous@ens-lyon.fr>
> I would like to write something like
>
> <<
> class type o =
> object
> method react: unit
> end
>
> module type O =
> sig
> type t :> o (* sigh... *)
> end
>
> module R(M: O) =
> struct
> let l: M.t list ref = []
> let register (o: M.t) = l := o :: !l
> let react() = List.iter (fun o -> o#react) !l
> end
> >>
The closest I can see to what you ask for is
module type O = sig
type t
val as_o : t -> o
end
module R(M: O) = struct
let l: M.t list ref = ref []
let register (o: M.t) = l := o :: !l
let react() = List.iter (fun o -> (M.as_o o)#react) !l
end
module RO = R(struct type t = o let as_o x = x end)
Then your second layer would be
class type o' = object
inherit o
method render: unit
end
module type O' = sig
include O
val as_o' : t -> o'
end
module R(M: O') = struct
include R(M)
let render() = List.iter (fun o -> (M.as_o' o)#render) !l
end
module O' = struct
type t = o'
let as_o x = (x : t :> o)
let as_o' x = x
end
module RO' = R(O')
> Is it unsound to let a functor use an object type ?
> (not to inherit from the class,
> just to use the methods of objects belonging to this type)
This isn't a problem of soundness.
There is just no such thing as a "partially abstract" object type.
But as shown above, you can easily simulate it by coupling an abstract
type with a coercion to an object type.
Note however that it would be probably simpler to turn your functors
into parameterized classes: then you can specify constraints on the
parameters with #-types.
class ['a] r = object
constraint 'a = #o
val mutable l : 'a list = []
method register o = l <- o :: l
method react = List.iter (fun o -> o#react) l
end
class ['a] r' = object
constraint 'a = #o'
inherit ['a] r
method render = List.iter (fun o -> o#render) l
end
But I don't know what you have precisely in mind.
Jacques
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] functors and objects
2004-02-04 2:57 ` [Caml-list] functors and objects Jacques Garrigue
@ 2004-02-05 8:55 ` Damien
2004-02-05 9:18 ` Jacques Garrigue
0 siblings, 1 reply; 9+ messages in thread
From: Damien @ 2004-02-05 8:55 UTC (permalink / raw)
To: caml-list
On Wed, 04 Feb 2004 11:57:45 +0900 Jacques Garrigue wrote:
> The closest I can see to what you ask for is
>
> module type O = sig
> type t
> val as_o : t -> o
> end
> ...
>
> This isn't a problem of soundness.
> There is just no such thing as a "partially abstract" object type.
there is no such thing...
...in the type system or in the compiler ?
Sorry for mixing variants and objects again,
but I have got the feeling that since the example I posted with variants
works, the first example with objects could/should work :
It seems quite natural and reasonable. So why should it be rejected...
I don't really see what can prevent the compiler to do it.
It looks like an additional check in the type checker,
and almost nothing in the compiler
(that's just a feeling, I never looked at ocamlc sources...)
> But as shown above, you can easily simulate it by coupling an abstract
> type with a coercion to an object type.
still curious : are such "coercion identity functions" eliminated by the
compiler ?
> Note however that it would be probably simpler to turn your functors
> into parameterized classes: then you can specify constraints on the
> parameters with #-types.
yes, the project is currently written with classes like
['reactor] obj
['obj] reactor
I was just wondering whether the class "reactor"
could be translated into a module, since it is instantiated only once.
cheers,
damien
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] functors and objects
2004-02-05 8:55 ` Damien
@ 2004-02-05 9:18 ` Jacques Garrigue
2004-02-05 13:45 ` Damien
0 siblings, 1 reply; 9+ messages in thread
From: Jacques Garrigue @ 2004-02-05 9:18 UTC (permalink / raw)
To: Damien.Pous; +Cc: caml-list
From: Damien <Damien.Pous@ens-lyon.fr>
> > This isn't a problem of soundness.
> > There is just no such thing as a "partially abstract" object type.
> there is no such thing...
> ...in the type system or in the compiler ?
>
> Sorry for mixing variants and objects again,
> but I have got the feeling that since the example I posted with variants
> works, the first example with objects could/should work :
> It seems quite natural and reasonable. So why should it be rejected...
Because instanciation/specialization only works for values, not for
types.
This is reasonable enough: once you have defined a type, you may use
it both in covariant and contravariant positions, so allowing to
specialize it would be unsound.
(So, yes, in the long run this is a soundness problem.)
The solution you describe with polymorphic variants use values, so
specialization works as expected.
> I don't really see what can prevent the compiler to do it.
> It looks like an additional check in the type checker,
> and almost nothing in the compiler
> (that's just a feeling, I never looked at ocamlc sources...)
Have a look if you have lots of free time :-)
> > But as shown above, you can easily simulate it by coupling an abstract
> > type with a coercion to an object type.
> still curious : are such "coercion identity functions" eliminated by the
> compiler ?
Unfortunately, no.
In general, functorial code (or object-oriented code) is much less
optimized than a first order style.
But it's not going to be very expensive either: just a few more jumps.
Jacques Garrigue
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] functors and objects
2004-02-05 9:18 ` Jacques Garrigue
@ 2004-02-05 13:45 ` Damien
2004-02-06 1:30 ` Jacques Garrigue
0 siblings, 1 reply; 9+ messages in thread
From: Damien @ 2004-02-05 13:45 UTC (permalink / raw)
To: caml-list
On Thu, 05 Feb 2004 18:18:45 +0900 Jacques Garrigue wrote:
> Because instanciation/specialization only works for values, not for
> types.
> This is reasonable enough: once you have defined a type, you may use
> it both in covariant and contravariant positions, so allowing to
> specialize it would be unsound.
> (So, yes, in the long run this is a soundness problem.)
I don't see the point :-(
module type O =
sig
type " t :> o "
end
can be read as
module type O =
sig
type ellipsis (* abstract *)
type t = " <o; ellipsis> "
end
therefore, a functor F(M: O) cannot create objects of type t without the
help of M.
module F(M: O) =
struct
(* correct invariant use *)
let l: M.t list ref = ref []
(* correct covariant use *)
let get: unit -> M.t list = fun () -> !l
(* correct contravariant use *)
let add: M.t -> unit = fun o -> l := o : !l
(* unsound has type `unit -> o' but not `unit -> M.t' *)
let unsound() = new object method react = () end
end
where is it wrong ?
damien
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [Caml-list] functors and objects
2004-02-05 13:45 ` Damien
@ 2004-02-06 1:30 ` Jacques Garrigue
0 siblings, 0 replies; 9+ messages in thread
From: Jacques Garrigue @ 2004-02-06 1:30 UTC (permalink / raw)
To: Damien.Pous; +Cc: caml-list
From: Damien <Damien.Pous@ens-lyon.fr>
> On Thu, 05 Feb 2004 18:18:45 +0900 Jacques Garrigue wrote:
>
> > Because instanciation/specialization only works for values, not for
> > types.
> > This is reasonable enough: once you have defined a type, you may use
> > it both in covariant and contravariant positions, so allowing to
> > specialize it would be unsound.
> > (So, yes, in the long run this is a soundness problem.)
>
> I don't see the point :-(
>
> module type O =
> sig
> type " t :> o "
> end
>
> can be read as
>
> module type O =
> sig
> type ellipsis (* abstract *)
> type t = " <o; ellipsis> "
> end
>
> therefore, a functor F(M: O) cannot create objects of type t without the
> help of M.
I see.
This way you can coerce from t to o, but not the other way round.
The trouble is just that in ocaml, the row variable of an object type
is not a type in itself (even if it uses the same datatype
representation in the compiler).
There are actually three possible row-endings:
Tvar -> an extensible row, as the one in "#o"
Tnil -> a closed row, as in "o"
Tunivar -> an existential row variable, unifies only with itself,
and must be bound locally. used for polymorphic variables in
polymorphic methods.
What you are asking for is actually adding a 4th form,
Tconstr (path, args, memo) ->
extension through a type (abstract or concrete)
Not only would this require to extend all existing handling of
row-endings (which occur in many places in the compiler), but this
should also include the possibility that the extension is concrete
(needed as you want to be able to add methods through functor
application), and should be expanded when looking for a method. This
breaks another assumption in the compiler (that no expansion is needed
to access the method types.)
But all this technical part is possible.
The real question is: would it be useful?
Note that compared to a class-based approach, the extensibility would
still be weaker: in declaration
type ('a1,..,'an) t :> ('a1,..,'an) o
only the type variables 'a1 to 'an can be used in extra methods.
This is a well-known problem with functors, but would be even more
problematic if we allow this kind of semi-abstract types.
For all these reasons, your idea, while theoretically interesting,
does not attract me so much: lots of work for a rather weak result,
while there are already simpler ways to do the same thing.
Jacques Garrigue
-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2004-02-06 1:30 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-02-03 18:06 [Caml-list] functors and objects Damien
2004-02-03 19:37 ` Matt Gushee
2004-02-03 19:39 ` [Caml-list] functors and objects' Matt Gushee
2004-02-03 20:26 ` Damien Pous
2004-02-04 2:57 ` [Caml-list] functors and objects Jacques Garrigue
2004-02-05 8:55 ` Damien
2004-02-05 9:18 ` Jacques Garrigue
2004-02-05 13:45 ` Damien
2004-02-06 1:30 ` Jacques Garrigue
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox