caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* oo type question
@ 2008-03-06 12:52 Michael Wohlwend
  2008-03-06 13:18 ` [Caml-list] " Peng Zang
  0 siblings, 1 reply; 6+ messages in thread
From: Michael Wohlwend @ 2008-03-06 12:52 UTC (permalink / raw)
  To: caml-list


I try to do the following:

I have some objects (all with an id method):
let o1 = object method id = 1  method hi = "hi" end
let o2 = object method id = 2  method ho = "ho" end

and now:

class store = object 
	val mutable  ids = []
	method add o =  ids <- o#id :: ids
end

this doesn't work, since the hidden type variable in the argument to add (I 
think). But why can't the compiler just set o to be of type < obj:int; ..> ?.
So I try:
class ['a] store = object 
	val mutable  ids = []
	method add (o: 'a) =  ids <- o#id :: ids
end;;

...but...

let s = new store ;;
give the type:
val s : < id : '_a; _.. > store = <obj>

so this doesn't work:

s#add o1;
s#add o2

his expression has type < hi : string; id : int > but is here used with type
  < ha : string; id : int >
The second object type has no method ho

If I define a function, say:
let f o = o#id;;
I get :
val f : < id : 'a; .. > -> 'a = <fun>
so this works:
f o1; f o2


why does this not work with methods?

cheers
 Michael


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] oo type question
  2008-03-06 12:52 oo type question Michael Wohlwend
@ 2008-03-06 13:18 ` Peng Zang
  2008-03-06 15:45   ` Michael Wohlwend
  0 siblings, 1 reply; 6+ messages in thread
From: Peng Zang @ 2008-03-06 13:18 UTC (permalink / raw)
  To: caml-list; +Cc: Michael Wohlwend

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

The problem is that class ['a] store after adding o1 only accepts objects that 
have both an id method AND a hi method.  So to make it work you need to do 
something like this:


let o1 = object method id = 1  method hi = "hi" end;;
let o2 = object method id = 2  method ho = "ho" end;;
class ['a] store = object 
  val mutable ids = []
  method add (o: 'a) =  ids <- o#id :: ids
end;;
let s = new store ;;
s#add (o1 :> <id:int>);;
s#add (o2 :> <id:int>);;

Note how I coerce o1 and o2 both to a subtype before adding.  Now the problem 
goes away because to the s#add method o1 and o2 have the same type.



BUT, what I think you really want is a polymorphic method, not a polymorphic 
class.  The manual has a decent explanation under polymohrphic methods in the 
Objects section.  So I think you want this:


let o1 = object method id = 1  method hi = "hi" end;;
let o2 = object method id = 2  method ho = "ho" end;;
class store = object 
  val mutable ids = []
  method add : 'a. <id:int; ..> as 'a -> unit = 
    fun o -> ids <- o#id :: ids
end;;

let s = new store ;;
s#add o1;;
s#add o2;;



Peng



On Thursday 06 March 2008 07:52:38 am Michael Wohlwend wrote:
> I try to do the following:
>
> I have some objects (all with an id method):
> let o1 = object method id = 1  method hi = "hi" end
> let o2 = object method id = 2  method ho = "ho" end
>
> and now:
>
> class store = object
> 	val mutable  ids = []
> 	method add o =  ids <- o#id :: ids
> end
>
> this doesn't work, since the hidden type variable in the argument to add (I
> think). But why can't the compiler just set o to be of type < obj:int; ..>
> ?. So I try:
> class ['a] store = object
> 	val mutable  ids = []
> 	method add (o: 'a) =  ids <- o#id :: ids
> end;;
>
> ...but...
>
> let s = new store ;;
> give the type:
> val s : < id : '_a; _.. > store = <obj>
>
> so this doesn't work:
>
> s#add o1;
> s#add o2
>
> his expression has type < hi : string; id : int > but is here used with
> type < ha : string; id : int >
> The second object type has no method ho
>
> If I define a function, say:
> let f o = o#id;;
> I get :
> val f : < id : 'a; .. > -> 'a = <fun>
> so this works:
> f o1; f o2
>
>
> why does this not work with methods?
>
> cheers
>  Michael
>
> _______________________________________________
> Caml-list mailing list. Subscription management:
> http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
> Archives: http://caml.inria.fr
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.7 (GNU/Linux)

iD8DBQFHz+8nfIRcEFL/JewRAm9iAJ9CsOmurw8tI2VUls4noUPN8L0TXgCeN6Zk
i0NwtHUdj2XN5lnZbCSbxtw=
=MHlA
-----END PGP SIGNATURE-----


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] oo type question
  2008-03-06 13:18 ` [Caml-list] " Peng Zang
@ 2008-03-06 15:45   ` Michael Wohlwend
  2008-03-06 16:58     ` Peng Zang
  2008-03-10  8:20     ` Jacques Garrigue
  0 siblings, 2 replies; 6+ messages in thread
From: Michael Wohlwend @ 2008-03-06 15:45 UTC (permalink / raw)
  To: peng.zang, caml-list

Am Donnerstag, 6. März 2008 14:18:29 schrieb Peng Zang:
> let s = new store ;;
> s#add (o1 :> <id:int>);;
> s#add (o2 :> <id:int>);;

> Note how I coerce o1 and o2 both to a subtype before adding.  Now the
> problem goes away because to the s#add method o1 and o2 have the same type.

yes, that's the easy way, but then I have to do casts all over the place, not 
very nice

> BUT, what I think you really want is a polymorphic method, not a
> polymorphic class.  The manual has a decent explanation under polymohrphic
> methods in the Objects section.  So I think you want this:
>   method add : 'a. <id:int; ..> as 'a -> unit =
>     fun o -> ids <- o#id :: ids

I know that version and of course it works. I only  didn't understand (and 
still do not) why it's not possible to just declare
method add (a: #someClass) ... which seems natural for me. And it works for 
normal functions that way.

If you have many classes (actually it's for adding widgets to group widgets) 
it seems just a bit too complicated and not a natural way to declare such a 
simple thing.


thanks,
 Michael


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] oo type question
  2008-03-06 15:45   ` Michael Wohlwend
@ 2008-03-06 16:58     ` Peng Zang
  2008-03-10  8:20     ` Jacques Garrigue
  1 sibling, 0 replies; 6+ messages in thread
From: Peng Zang @ 2008-03-06 16:58 UTC (permalink / raw)
  To: Michael Wohlwend; +Cc: caml-list

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Thursday 06 March 2008 10:45:30 am Michael Wohlwend wrote:
> Am Donnerstag, 6. März 2008 14:18:29 schrieb Peng Zang:
> > let s = new store ;;
> > s#add (o1 :> <id:int>);;
> > s#add (o2 :> <id:int>);;
> >
> > Note how I coerce o1 and o2 both to a subtype before adding.  Now the
> > problem goes away because to the s#add method o1 and o2 have the same
> > type.
>
> yes, that's the easy way, but then I have to do casts all over the place,
> not very nice
>
> > BUT, what I think you really want is a polymorphic method, not a
> > polymorphic class.  The manual has a decent explanation under
> > polymohrphic methods in the Objects section.  So I think you want this:
> >   method add : 'a. <id:int; ..> as 'a -> unit =
> >     fun o -> ids <- o#id :: ids
>
> I know that version and of course it works. I only  didn't understand (and
> still do not) why it's not possible to just declare
> method add (a: #someClass) ... which seems natural for me. And it works for
> normal functions that way.
>
> If you have many classes (actually it's for adding widgets to group
> widgets) it seems just a bit too complicated and not a natural way to
> declare such a simple thing.

Hmmm... I do not know of another easy way to do this.  Polymorphic methods 
cannot be inferred in general because IIRC it is undecidable?  That said, 
this special case seems simple enough.

Other (possibly lame) suggestions:

1) You can give some nice type alias to "<id:int; ..> as 'a" so the type 
specification looks simpler

2) You can go with the polymorphic class case and write a small helper 
function, eg:

  let addwithcoerce s a = s#add (a :> <id:int>)

to hide the coercions.

Perhaps others on this list will have additional ideas too.

Regards,
Peng


-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.7 (GNU/Linux)

iD8DBQFH0CKmfIRcEFL/JewRAkLXAKCLog1BC8wViOJ+yF/TjoG4T+5KDACgxXJ1
HiUc6i+D9bvpKWn/zCbWEf0=
=R6fR
-----END PGP SIGNATURE-----


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] oo type question
  2008-03-06 15:45   ` Michael Wohlwend
  2008-03-06 16:58     ` Peng Zang
@ 2008-03-10  8:20     ` Jacques Garrigue
  2008-03-10  8:38       ` Michael Wohlwend
  1 sibling, 1 reply; 6+ messages in thread
From: Jacques Garrigue @ 2008-03-10  8:20 UTC (permalink / raw)
  To: micha-1; +Cc: caml-list

From: Michael Wohlwend <micha-1@fantasymail.de>
> Am Donnerstag, 6. März 2008 14:18:29 schrieb Peng Zang:
> > BUT, what I think you really want is a polymorphic method, not a
> > polymorphic class.  The manual has a decent explanation under polymohrphic
> > methods in the Objects section.  So I think you want this:
> >   method add : 'a. <id:int; ..> as 'a -> unit =
> >     fun o -> ids <- o#id :: ids
> 
> I know that version and of course it works. I only  didn't understand (and 
> still do not) why it's not possible to just declare
> method add (a: #someClass) ... which seems natural for me. And it works for 
> normal functions that way.
> 
> If you have many classes (actually it's for adding widgets to group widgets) 
> it seems just a bit too complicated and not a natural way to declare such a 
> simple thing.

One reason it is not so simple for methods is that they belong to
objects. So if you write
   method add (a : #someClass) ...
which is really equivalent to
   method add (a : <some methods; .. > as 'a)
it is not clear where the variable should be bound. This could be
either at the class level (for the whole object, as in your first
example) or at the method level. So you need an explicit syntax to
tell which one it is to the type system.

Another reason, a bit more technical, is that polymorphic methods do
not behave like polymorhic functions. In particular, they cannot be
instantiated automatically when needed: i.e., you cannot pass an
object with a polymorphic method where a monomorphic method is
expected. Currently, even subtyping is not allowed between polymorphic
methods and their monomorphics instances (this may change in 3.11).
So this seems a bad idea to create a potentially incompatible
polymorphic method without some explicit direction from the
programmer. Note that the type annotation #someClass is not sufficient
direction, because it does not request any polymorphism: it is not an
error for the actual method to be of type "someClass -> ..." (I'm not
sure it is what most people expect, but it is the way ocaml is
defined)

A small remark yet: in interfaces (and class types) it is ok to write
  class c : object
    method add : #someClass -> ...
  end
Here it is automatically assumed that the type variable is bound at
the method level.

Jacques Garrigue


^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Caml-list] oo type question
  2008-03-10  8:20     ` Jacques Garrigue
@ 2008-03-10  8:38       ` Michael Wohlwend
  0 siblings, 0 replies; 6+ messages in thread
From: Michael Wohlwend @ 2008-03-10  8:38 UTC (permalink / raw)
  To: caml-list

Am Montag, 10. März 2008 09:20:43 schrieb Jacques Garrigue:

ok, thanks for the explanations,

> From: Michael Wohlwend <micha-1@fantasymail.de>
>
> A small remark yet: in interfaces (and class types) it is ok to write
>   class c : object
>     method add : #someClass -> ...
>   end
> Here it is automatically assumed that the type variable is bound at
> the method level.

ah o.k,  nice to know. I'll try that.
(I thought declaring something to be of type #class is similar to 
the "implenents" declaration in java, where you can pass objects without a 
cast to methods accepting arguments of that interface, which I find 
nice :-) )
I like the oncept of ocaml to make no implizit casts; only when using objects 
I think casting to an upper class (!) should be done automatically since it's 
one of the basic "features" of oo programming. 

 Michael


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2008-03-10  8:42 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-03-06 12:52 oo type question Michael Wohlwend
2008-03-06 13:18 ` [Caml-list] " Peng Zang
2008-03-06 15:45   ` Michael Wohlwend
2008-03-06 16:58     ` Peng Zang
2008-03-10  8:20     ` Jacques Garrigue
2008-03-10  8:38       ` Michael Wohlwend

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).