caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Why can't I call a function over a subclass?
@ 2007-10-05  7:48 Luca de Alfaro
  2007-10-05  8:01 ` [Caml-list] " Florian Hars
                   ` (2 more replies)
  0 siblings, 3 replies; 22+ messages in thread
From: Luca de Alfaro @ 2007-10-05  7:48 UTC (permalink / raw)
  To: Inria Ocaml Mailing List

[-- Attachment #1: Type: text/plain, Size: 1155 bytes --]

Consider the following sample code, that refuses to type check in Ocaml:

---start---

class r (x_init: int) = object
  method get_x : int = x_init
end

let f (r1: r) (r2: r) : bool = (r1#get_x = r2#get_x)

class r' (x_init: int) = object
  inherit r x_init
  method get_xx : int = 2 * x_init
end

let q (r1: r') (r2: r') = f r1 r2

---end---

r' is a subclass of r.  The compiler complains:

File "class1.ml", line 12, characters 28-30:
This expression has type r' but is here used with type r
The second object type has no method get_xx

Now, I know r does not have method get_xx, but why on Earth should this
matter?
I can see that there can be an error if I feed to f something that has FEWER
methods, but why should it be an error to feed to
f something with MORE methods??

The absurdity continues: if I instead declare f as:

let f (r1: <get_x: int; ..>) (r2: <get_x: int; ..>) : bool =
  (r1#get_x = r2#get_x)

then the code type-checks.  Why is this fine but f: r -> r -> bool causes a
type error?
The situation does not make sense to me.  Can someone shed some light on
what is going on?
(This with Ocaml 3.10.0 in case it matters)

Best,

Luca

[-- Attachment #2: Type: text/html, Size: 1413 bytes --]

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

* Re: [Caml-list] Why can't I call a function over a subclass?
  2007-10-05  7:48 Why can't I call a function over a subclass? Luca de Alfaro
@ 2007-10-05  8:01 ` Florian Hars
  2007-10-05  8:08   ` Luca de Alfaro
  2007-10-05 10:30   ` David Teller
  2007-10-05  8:07 ` [Caml-list] " Pietro Abate
  2007-10-05 10:55 ` Andrej Bauer
  2 siblings, 2 replies; 22+ messages in thread
From: Florian Hars @ 2007-10-05  8:01 UTC (permalink / raw)
  To: Luca de Alfaro; +Cc: Inria Ocaml Mailing List

Luca de Alfaro schrieb:
> The absurdity continues:

This is not absurd, this is the documented correct behaviuor.
If *you* decide that f must only accept arguments of *exactly*
type r, the typechecker enforces your decision, as it does if
you decide that f may also accept subtypes of r (as long as your
decisions are consistent within he type system).

Yours, Florian.


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

* Re: [Caml-list] Why can't I call a function over a subclass?
  2007-10-05  7:48 Why can't I call a function over a subclass? Luca de Alfaro
  2007-10-05  8:01 ` [Caml-list] " Florian Hars
@ 2007-10-05  8:07 ` Pietro Abate
  2007-10-05 10:55 ` Andrej Bauer
  2 siblings, 0 replies; 22+ messages in thread
From: Pietro Abate @ 2007-10-05  8:07 UTC (permalink / raw)
  To: caml-list, Inria Ocaml Mailing List

On Fri, Oct 05, 2007 at 12:48:54AM -0700, Luca de Alfaro wrote:
> r' is a subclass of r.  The compiler complains:
> 
> File "class1.ml", line 12, characters 28-30:
> This expression has type r' but is here used with type r
> The second object type has no method get_xx

I see two solutions: Either you explicitly coerce the type of r' to r
so to match its (explicit) signature:
let q (r1: r') (r2: r') = f (r1 :> r) (r2 :> r) 

or you remove the type constraints from f and you let ocaml do the
rest.

let f r1  r2 = (r1#get_x = r2#get_x)
let q (r1: r') (r2: r') = f r1 r2

why do you want to specify the type of f ? The minimal information
needed is that it's an object with a method get_x and this can be
inferred by the type checker. Then all objects with a method get_x will
work even if not explicitly a subclass (iirc). Usually I don't specify
type constraints if not absolutely necessary and I use a signature to
wrap the module in the end.

:)
pp

-- 
++ 
++ "All great truths begin as blasphemies." -George Bernard Shaw
++ Please avoid sending me Word or PowerPoint attachments.
   See http://www.gnu.org/philosophy/no-word-attachments.html


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

* Re: [Caml-list] Why can't I call a function over a subclass?
  2007-10-05  8:01 ` [Caml-list] " Florian Hars
@ 2007-10-05  8:08   ` Luca de Alfaro
  2007-10-05  8:08     ` Fwd: " Luca de Alfaro
  2007-10-05 11:08     ` Vincent Aravantinos
  2007-10-05 10:30   ` David Teller
  1 sibling, 2 replies; 22+ messages in thread
From: Luca de Alfaro @ 2007-10-05  8:08 UTC (permalink / raw)
  To: Inria Ocaml Mailing List

[-- Attachment #1: Type: text/plain, Size: 838 bytes --]

I don't understand this.  I thought the whole idea of oo programming was
that you could use a subclass in place of a superclass...

I also thought that the strict typing of Ocaml was there to avoid runtime
errors, but if so, why does it complain in this situation, when no runtime
error can possibly happen?

It seems to me that the idea of oo programming is broken for no good
reason...

Luca

On 10/5/07, Florian Hars <hars@bik-gmbh.de> wrote:
>
> Luca de Alfaro schrieb:
> > The absurdity continues:
>
> This is not absurd, this is the documented correct behaviuor.
> If *you* decide that f must only accept arguments of *exactly*
> type r, the typechecker enforces your decision, as it does if
> you decide that f may also accept subtypes of r (as long as your
> decisions are consistent within he type system).
>
> Yours, Florian.
>

[-- Attachment #2: Type: text/html, Size: 1155 bytes --]

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

* Fwd: [Caml-list] Why can't I call a function over a subclass?
  2007-10-05  8:08   ` Luca de Alfaro
@ 2007-10-05  8:08     ` Luca de Alfaro
  2007-10-05 11:08     ` Vincent Aravantinos
  1 sibling, 0 replies; 22+ messages in thread
From: Luca de Alfaro @ 2007-10-05  8:08 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 1190 bytes --]

I meant to say: it seems to be that Ocaml breaks the principles of oo
programming for no good reason, in this case.

luca

---------- Forwarded message ----------
From: Luca de Alfaro <luca@dealfaro.org>
Date: Oct 5, 2007 1:08 AM
Subject: Re: [Caml-list] Why can't I call a function over a subclass?
To: Inria Ocaml Mailing List <caml-list@inria.fr>

I don't understand this.  I thought the whole idea of oo programming was
that you could use a subclass in place of a superclass...

I also thought that the strict typing of Ocaml was there to avoid runtime
errors, but if so, why does it complain in this situation, when no runtime
error can possibly happen?

It seems to me that the idea of oo programming is broken for no good
reason...

Luca

On 10/5/07, Florian Hars < hars@bik-gmbh.de> wrote:
>
> Luca de Alfaro schrieb:
> > The absurdity continues:
>
> This is not absurd, this is the documented correct behaviuor.
> If *you* decide that f must only accept arguments of *exactly*
> type r, the typechecker enforces your decision, as it does if
> you decide that f may also accept subtypes of r (as long as your
> decisions are consistent within he type system).
>
> Yours, Florian.
>

[-- Attachment #2: Type: text/html, Size: 1856 bytes --]

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

* Re: [Caml-list] Why can't I call a function over a subclass?
  2007-10-05  8:01 ` [Caml-list] " Florian Hars
  2007-10-05  8:08   ` Luca de Alfaro
@ 2007-10-05 10:30   ` David Teller
  2007-10-05 10:53     ` Zheng Li
  1 sibling, 1 reply; 22+ messages in thread
From: David Teller @ 2007-10-05 10:30 UTC (permalink / raw)
  To: Florian Hars; +Cc: Luca de Alfaro, Inria Ocaml Mailing List

I agree with Luca that it's disconcerting. 
When r is a class, I would expect 
 let f (x:r) (y:r) =...
to have a type such as
 x :> r -> y :> r -> ...

Cheers,
 David

On Fri, 2007-10-05 at 10:01 +0200, Florian Hars wrote:
> Luca de Alfaro schrieb:
> > The absurdity continues:
> 
> This is not absurd, this is the documented correct behaviuor.
> If *you* decide that f must only accept arguments of *exactly*
> type r, the typechecker enforces your decision, as it does if
> you decide that f may also accept subtypes of r (as long as your
> decisions are consistent within he type system).
> 
> Yours, Florian.
> 
> _______________________________________________
> 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


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

* Re: Why can't I call a function over a subclass?
  2007-10-05 10:30   ` David Teller
@ 2007-10-05 10:53     ` Zheng Li
  2007-10-05 14:02       ` [Caml-list] " David Teller
  0 siblings, 1 reply; 22+ messages in thread
From: Zheng Li @ 2007-10-05 10:53 UTC (permalink / raw)
  To: caml-list

David Teller <David.Teller@ens-lyon.org> writes:
> I agree with Luca that it's disconcerting. 
> When r is a class, I would expect 

>  let f (x:r) (y:r) =...
This expression says f accept arguments of type [r], what you mean to say is: f
accept any arguments belong to [r]'s subtypes family. Then say it with

# let f (x:#r) (y:#r) = x#get_x = y#get_x
val f : #r -> #r -> bool = <fun>

-- 
Zheng Li
http://www.pps.jussieu.fr/~li


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

* Re: [Caml-list] Why can't I call a function over a subclass?
  2007-10-05  7:48 Why can't I call a function over a subclass? Luca de Alfaro
  2007-10-05  8:01 ` [Caml-list] " Florian Hars
  2007-10-05  8:07 ` [Caml-list] " Pietro Abate
@ 2007-10-05 10:55 ` Andrej Bauer
  2 siblings, 0 replies; 22+ messages in thread
From: Andrej Bauer @ 2007-10-05 10:55 UTC (permalink / raw)
  To: Luca de Alfaro; +Cc: Inria Ocaml Mailing List

Ocaml will compute types for you. If you want, you can also specify the 
types and it will repsect that. You specified the types of r1 and r2:

> let f (r1: r) (r2: r) : bool = (r1#get_x = r2#get_x)

Even though r' is a subclass  of r, a value of type r' is _not_ of type 
r (if your brain thinks in Java you might find this surprising--in which 
case we can talk about it):

# let a = new r' 5 ;;
val a : r' = <obj>
# (a : r);;
Characters 1-2:
   (a : r);;
    ^
This expression has type r' but is here used with type r
Only the first object type has a method get_xx

If you let Ocaml compute types on its own, your example will work as 
expected:

let f r1 r2 = (r1#get_x = r2#get_x)

Now the function of f is computed to be

val f : < get_x : 'a; .. > -> < get_x : 'a; .. > -> bool

So just let the machine worry about they types.

Andrej


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

* Re: [Caml-list] Why can't I call a function over a subclass?
  2007-10-05  8:08   ` Luca de Alfaro
  2007-10-05  8:08     ` Fwd: " Luca de Alfaro
@ 2007-10-05 11:08     ` Vincent Aravantinos
  2007-10-05 11:47       ` Christophe Raffalli
  1 sibling, 1 reply; 22+ messages in thread
From: Vincent Aravantinos @ 2007-10-05 11:08 UTC (permalink / raw)
  To: Luca de Alfaro; +Cc: Inria Ocaml Mailing List


Le 5 oct. 07 à 10:08, Luca de Alfaro a écrit :

> I don't understand this.  I thought the whole idea of oo  
> programming was that you could use a subclass in place of a  
> superclass...
>
> I also thought that the strict typing of Ocaml was there to avoid  
> runtime errors, but if so, why does it complain in this situation,  
> when no runtime error can possibly happen?
>
> It seems to me that the idea of oo programming is broken for no  
> good reason...

- This is absurd in an oo context. Here, the main paradigm is not oo.  
It is simply strongly typed. So if you write that a function expects  
a particular type, this function should be applied with this  
particular type and nothing else. *You* wrote this so you claimed for  
it.

You want more generality ? Then let the type checker do its job as  
Pietro said. *The default behaviour is not to write any type info.*  
If you stay with this you get the standard oo behaviour.

Annotations are there to give more info to the compiler in case it  
does infer what you have in mind.

- Strict typing of Ocaml is not to avoid runtime errors. It simply  
stays that if two types expected to be the same differ, we suppose  
*the program does not match what the programmer has in mind*. As a  
little side-effect, this can avoid runtime errors :)

If you keep this idea of "what the programmer has in mind", in this  
particular case you said to the compiler with your type annotation  
that what you had in mind was that the function only takes a r. What  
you said to the compiler was not what you had in mind.


And I insist again: the default behaviour (don't anotate) gives you  
what you would expect.

Cheers,
Vincent

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

* Re: [Caml-list] Why can't I call a function over a subclass?
  2007-10-05 11:08     ` Vincent Aravantinos
@ 2007-10-05 11:47       ` Christophe Raffalli
  0 siblings, 0 replies; 22+ messages in thread
From: Christophe Raffalli @ 2007-10-05 11:47 UTC (permalink / raw)
  To: Vincent Aravantinos; +Cc: Luca de Alfaro, Inria Ocaml Mailing List

[-- Attachment #1: Type: text/plain, Size: 803 bytes --]


The problem is that OCaml type-checker is unification based instead of subtyping-constraint based
and therefore require (useless) type cast in some place (with variant and objects) ... This is why
you get unnatural behaviour of the type-checker with oo and variant in OCaml ...


-- 
Christophe Raffalli
Universite de Savoie
Batiment Le Chablais, bureau 21
73376 Le Bourget-du-Lac Cedex

tel: (33) 4 79 75 81 03
fax: (33) 4 79 75 87 42
mail: Christophe.Raffalli@univ-savoie.fr
www: http://www.lama.univ-savoie.fr/~RAFFALLI
---------------------------------------------
IMPORTANT: this mail is signed using PGP/MIME
At least Enigmail/Mozilla, mutt or evolution
can check this signature. The public key is
stored on www.keyserver.net
---------------------------------------------


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 252 bytes --]

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

* Re: [Caml-list] Re: Why can't I call a function over a subclass?
  2007-10-05 10:53     ` Zheng Li
@ 2007-10-05 14:02       ` David Teller
  2007-10-05 14:59         ` Luca de Alfaro
  0 siblings, 1 reply; 22+ messages in thread
From: David Teller @ 2007-10-05 14:02 UTC (permalink / raw)
  To: Zheng Li; +Cc: caml-list

Sure. I'm just saying that this default behaviour is disconcerting.

In addition to which, while it does appear in the documentation, it's
rather well hidden inside section 3.11 "Polymorphic methods" -- even
though this is not a method.

Cheers,
 David

On Fri, 2007-10-05 at 12:53 +0200, Zheng Li wrote:
> David Teller <David.Teller@ens-lyon.org> writes:
> > I agree with Luca that it's disconcerting. 
> > When r is a class, I would expect 
> 
> >  let f (x:r) (y:r) =...
> This expression says f accept arguments of type [r], what you mean to say is: f
> accept any arguments belong to [r]'s subtypes family. Then say it with
> 
> # let f (x:#r) (y:#r) = x#get_x = y#get_x
> val f : #r -> #r -> bool = <fun>
> 


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

* Re: [Caml-list] Re: Why can't I call a function over a subclass?
  2007-10-05 14:02       ` [Caml-list] " David Teller
@ 2007-10-05 14:59         ` Luca de Alfaro
  2007-10-05 15:12           ` Luca de Alfaro
  0 siblings, 1 reply; 22+ messages in thread
From: Luca de Alfaro @ 2007-10-05 14:59 UTC (permalink / raw)
  To: David Teller; +Cc: Zheng Li, caml-list

[-- Attachment #1: Type: text/plain, Size: 2309 bytes --]

The problem is also that the example I posted is a minimal instance of the
problem, but my real problem is much harder to solve (or so I believe, let
me know if you have suggestions!).
My real problem is that I have a class r, that internally, in many places,
uses objects of a class p.
Then I subclass r into r', and in r', I need to replace objects of type p
with objects of type p', a subclass of p.
Inside r I have a method do_work that does something like, in its body:

 ...
let x = new Pclass.p in
...

Now, if I cut-and-paste the code of do_work from r to r', and change the
above line in:
let x = new Pclass.p' in
then everything works.
If instead I replace the code in r with:

method make_p = new Pclass.p

...
let x = make_p in
...

so that in r', I just need to override make_p with:

method make_p = new Pclass.p'

then the code does not type check --- and I don't know why, and in any case
it is not logical to me.
What would be the solution in this case?  The classes p, p' are used in many
places in r, r', but the error only occurs when I do the above change.
Any help would be appreciated --- at least, so that I understand better how
not to break my code...

Luca


On 10/5/07, David Teller <David.Teller@ens-lyon.org> wrote:
>
> Sure. I'm just saying that this default behaviour is disconcerting.
>
> In addition to which, while it does appear in the documentation, it's
> rather well hidden inside section 3.11 "Polymorphic methods" -- even
> though this is not a method.
>
> Cheers,
> David
>
> On Fri, 2007-10-05 at 12:53 +0200, Zheng Li wrote:
> > David Teller <David.Teller@ens-lyon.org> writes:
> > > I agree with Luca that it's disconcerting.
> > > When r is a class, I would expect
> >
> > >  let f (x:r) (y:r) =...
> > This expression says f accept arguments of type [r], what you mean to
> say is: f
> > accept any arguments belong to [r]'s subtypes family. Then say it with
> >
> > # let f (x:#r) (y:#r) = x#get_x = y#get_x
> > val f : #r -> #r -> bool = <fun>
> >
>
> _______________________________________________
> 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
>

[-- Attachment #2: Type: text/html, Size: 3241 bytes --]

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

* Re: [Caml-list] Re: Why can't I call a function over a subclass?
  2007-10-05 14:59         ` Luca de Alfaro
@ 2007-10-05 15:12           ` Luca de Alfaro
       [not found]             ` <20071005152130.M41697@cs.unm.edu>
  0 siblings, 1 reply; 22+ messages in thread
From: Luca de Alfaro @ 2007-10-05 15:12 UTC (permalink / raw)
  To: David Teller; +Cc: Zheng Li, caml-list

[-- Attachment #1: Type: text/plain, Size: 2696 bytes --]

I am sorry - I am wrong.  I get an error in both cases listed below.
So the behavior is disconcerting to me, and no clear elegant solution
exists, but at least the behavior is consistent.

Luca

On 10/5/07, Luca de Alfaro <luca@dealfaro.org> wrote:
>
> The problem is also that the example I posted is a minimal instance of the
> problem, but my real problem is much harder to solve (or so I believe, let
> me know if you have suggestions!).
> My real problem is that I have a class r, that internally, in many places,
> uses objects of a class p.
> Then I subclass r into r', and in r', I need to replace objects of type p
> with objects of type p', a subclass of p.
> Inside r I have a method do_work that does something like, in its body:
>
>  ...
> let x = new Pclass.p in
> ...
>
> Now, if I cut-and-paste the code of do_work from r to r', and change the
> above line in:
> let x = new Pclass.p' in
> then everything works.
> If instead I replace the code in r with:
>
> method make_p = new Pclass.p
>
> ...
> let x = make_p in
> ...
>
> so that in r', I just need to override make_p with:
>
> method make_p = new Pclass.p'
>
> then the code does not type check --- and I don't know why, and in any
> case it is not logical to me.
> What would be the solution in this case?  The classes p, p' are used in
> many places in r, r', but the error only occurs when I do the above change.
> Any help would be appreciated --- at least, so that I understand better
> how not to break my code...
>
> Luca
>
>
> On 10/5/07, David Teller <David.Teller@ens-lyon.org> wrote:
> >
> > Sure. I'm just saying that this default behaviour is disconcerting.
> >
> > In addition to which, while it does appear in the documentation, it's
> > rather well hidden inside section 3.11 "Polymorphic methods" -- even
> > though this is not a method.
> >
> > Cheers,
> > David
> >
> > On Fri, 2007-10-05 at 12:53 +0200, Zheng Li wrote:
> > > David Teller <David.Teller@ens-lyon.org> writes:
> > > > I agree with Luca that it's disconcerting.
> > > > When r is a class, I would expect
> > >
> > > >  let f (x:r) (y:r) =...
> > > This expression says f accept arguments of type [r], what you mean to
> > say is: f
> > > accept any arguments belong to [r]'s subtypes family. Then say it with
> > >
> > > # let f (x:#r) (y:#r) = x#get_x = y#get_x
> > > val f : #r -> #r -> bool = <fun>
> > >
> >
> > _______________________________________________
> > 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
> >
>
>

[-- Attachment #2: Type: text/html, Size: 4296 bytes --]

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

* Re: [Caml-list] Re: Why can't I call a function over a subclass?
       [not found]             ` <20071005152130.M41697@cs.unm.edu>
@ 2007-10-05 15:49               ` Luca de Alfaro
  2007-10-05 16:34                 ` Edgar Friendly
                                   ` (2 more replies)
  0 siblings, 3 replies; 22+ messages in thread
From: Luca de Alfaro @ 2007-10-05 15:49 UTC (permalink / raw)
  To: William D. Neumann, Inria Ocaml Mailing List

[-- Attachment #1: Type: text/plain, Size: 1476 bytes --]

Yes, here is some code.  Any help would be very much appreciated.
The following fails to type check:

class p (x: int) = object
  method plus1 : int = x + 1
end

class p2 (x: int) = object
  inherit p x
  method plus2 : int = x + 2
end

class r = object (self)
  val mutable l = []
  method make_el x = new p x
  method add (x: int) : unit = l <- (self#make_el x) :: l
  method length : int = List.length l
  method total : int = List.fold_left (fun t el -> t + el#plus1) 0 l
end

class r2 = object
  inherit r
  method make_el x = new p2 x
  method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l
end

What I am trying to do is to replace, in l, elements of type p with elements
of type p2, so that my class r2 can offer more methods (or use them
internally).  However, the compiler complains that p2 and p are not
compatible, because p does not have method plus2 (in spite of the fact that
no runtime error can occur).

I am not a deep expert of Ocaml type system for classes, as you might have
guessed by now, so if someone were able to suggest a set of type
casts/notations/... that would make the above go through, I would be very
grateful.
In my real (large) code, I use the elements of the list l in many places
inside the code of r (and by inheritance, r2).





Do you have any code that we can look at to see what the problem is?  Can
> you perhaps construct a small yet complete example that demonstartes the
> issue?
>
> --
>
> William D. Neumann
>
>

[-- Attachment #2: Type: text/html, Size: 1896 bytes --]

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

* Re: [Caml-list] Re: Why can't I call a function over a subclass?
  2007-10-05 15:49               ` Luca de Alfaro
@ 2007-10-05 16:34                 ` Edgar Friendly
  2007-10-05 17:39                   ` Luca de Alfaro
  2007-10-05 19:48                 ` Why can't I call a function over a subclass? Zheng Li
  2007-10-09  4:18                 ` Jacques Garrigue
  2 siblings, 1 reply; 22+ messages in thread
From: Edgar Friendly @ 2007-10-05 16:34 UTC (permalink / raw)
  To: Luca de Alfaro; +Cc: William D. Neumann, Inria Ocaml Mailing List

Luca de Alfaro wrote:
> Yes, here is some code.  Any help would be very much appreciated.
> The following fails to type check:
> 
> class p (x: int) = object
>   method plus1 : int = x + 1
> end
> 
> class p2 (x: int) = object
>   inherit p x
>   method plus2 : int = x + 2
> end
> 
> class r = object (self)
>   val mutable l = []
>   method make_el x = new p x
>   method add (x: int) : unit = l <- (self#make_el x) :: l
>   method length : int = List.length l
>   method total : int = List.fold_left (fun t el -> t + el#plus1) 0 l
> end
> 
> class r2 = object
>   inherit r
>   method make_el x = new p2 x
>   method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l
> end
> 
if I manually perform the inherit operation by pasting the code from r1
into r2, I get:

class r2 = object (self)
  val mutable l = []
  method make_el x = new p2 x
  method add (x: int) : unit = l <- (self#make_el x) :: l
  method length : int = List.length l
  method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l
end

which compiles just fine, and probably works as intended.  If I include
the original method make_el above the new one like this:
  method make_el x = new p x
  method make_el x = new p2 x
Ignoring the warning about overriding methods within the same class, we
come to the root of the type problem: make_el must have a type.  After
inference completes on the first line, make_el's type is determined to
be p.  The second make_el's type must match, but it doesn't.  I don't
see a solution for your problem that doesn't involve this kind of manual
expansion and removal of duplicate methods, but I'm fairly sure this is
the real problem for you.

E.


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

* Re: [Caml-list] Re: Why can't I call a function over a subclass?
  2007-10-05 16:34                 ` Edgar Friendly
@ 2007-10-05 17:39                   ` Luca de Alfaro
  2007-10-05 17:49                     ` Martin Jambon
  0 siblings, 1 reply; 22+ messages in thread
From: Luca de Alfaro @ 2007-10-05 17:39 UTC (permalink / raw)
  To: Edgar Friendly; +Cc: William D. Neumann, Inria Ocaml Mailing List

[-- Attachment #1: Type: text/plain, Size: 2485 bytes --]

I thank you all for the help... in the end, I solved the practical problem
by collapsing p and p2 into the same class -- not so nice, but it works, and
it is simpler than other solutions.

But the larger issue is: when a type is used for an input parameters, as the
type p in:
f : int -> p -> bool
why does the compiler have to complain that p has too many methods?
Would it not be possible to make the type checker smarter, and ensure that
when p is an input type, it is ok to have more methods?
And for output types as well, it would seem?
In other words, what is that fundamentally breaks if one were to change the
ocaml type checker in this way?

Luca

On 10/5/07, Edgar Friendly <thelema314@gmail.com> wrote:
>
> Luca de Alfaro wrote:
> > Yes, here is some code.  Any help would be very much appreciated.
> > The following fails to type check:
> >
> > class p (x: int) = object
> >   method plus1 : int = x + 1
> > end
> >
> > class p2 (x: int) = object
> >   inherit p x
> >   method plus2 : int = x + 2
> > end
> >
> > class r = object (self)
> >   val mutable l = []
> >   method make_el x = new p x
> >   method add (x: int) : unit = l <- (self#make_el x) :: l
> >   method length : int = List.length l
> >   method total : int = List.fold_left (fun t el -> t + el#plus1) 0 l
> > end
> >
> > class r2 = object
> >   inherit r
> >   method make_el x = new p2 x
> >   method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l
> > end
> >
> if I manually perform the inherit operation by pasting the code from r1
> into r2, I get:
>
> class r2 = object (self)
>   val mutable l = []
>   method make_el x = new p2 x
>   method add (x: int) : unit = l <- (self#make_el x) :: l
>   method length : int = List.length l
>   method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l
> end
>
> which compiles just fine, and probably works as intended.  If I include
> the original method make_el above the new one like this:
>   method make_el x = new p x
>   method make_el x = new p2 x
> Ignoring the warning about overriding methods within the same class, we
> come to the root of the type problem: make_el must have a type.  After
> inference completes on the first line, make_el's type is determined to
> be p.  The second make_el's type must match, but it doesn't.  I don't
> see a solution for your problem that doesn't involve this kind of manual
> expansion and removal of duplicate methods, but I'm fairly sure this is
> the real problem for you.
>
> E.
>

[-- Attachment #2: Type: text/html, Size: 3209 bytes --]

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

* Re: [Caml-list] Re: Why can't I call a function over a subclass?
  2007-10-05 17:39                   ` Luca de Alfaro
@ 2007-10-05 17:49                     ` Martin Jambon
       [not found]                       ` <28fa90930710052153k2128bb63m5132455868eb2008@mail.gmail.com>
  0 siblings, 1 reply; 22+ messages in thread
From: Martin Jambon @ 2007-10-05 17:49 UTC (permalink / raw)
  To: Luca de Alfaro
  Cc: Edgar Friendly, Inria Ocaml Mailing List, William D. Neumann

On Fri, 5 Oct 2007, Luca de Alfaro wrote:

> But the larger issue is: when a type is used for an input parameters, as the
> type p in:
> f : int -> p -> bool
> why does the compiler have to complain that p has too many methods?

That's your point of view. The compiler complains about different types, 
but it doesn't know which one is intended:  does one object have 
too many methods or does the other object miss some methods?

With some experience, you will learn that artificially annotating types 
of objects or polymorphic variants leads to much clearer and earlier error 
messages.

So I would say that using ":>" is a rather mild annoyance, except that you 
have to learn what it means.


Martin


> Would it not be possible to make the type checker smarter, and ensure that
> when p is an input type, it is ok to have more methods?
> And for output types as well, it would seem?
> In other words, what is that fundamentally breaks if one were to change the
> ocaml type checker in this way?
>
> Luca
>
> On 10/5/07, Edgar Friendly <thelema314@gmail.com> wrote:
>>
>> Luca de Alfaro wrote:
>>> Yes, here is some code.  Any help would be very much appreciated.
>>> The following fails to type check:
>>>
>>> class p (x: int) = object
>>>   method plus1 : int = x + 1
>>> end
>>>
>>> class p2 (x: int) = object
>>>   inherit p x
>>>   method plus2 : int = x + 2
>>> end
>>>
>>> class r = object (self)
>>>   val mutable l = []
>>>   method make_el x = new p x
>>>   method add (x: int) : unit = l <- (self#make_el x) :: l
>>>   method length : int = List.length l
>>>   method total : int = List.fold_left (fun t el -> t + el#plus1) 0 l
>>> end
>>>
>>> class r2 = object
>>>   inherit r
>>>   method make_el x = new p2 x
>>>   method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l
>>> end
>>>
>> if I manually perform the inherit operation by pasting the code from r1
>> into r2, I get:
>>
>> class r2 = object (self)
>>   val mutable l = []
>>   method make_el x = new p2 x
>>   method add (x: int) : unit = l <- (self#make_el x) :: l
>>   method length : int = List.length l
>>   method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l
>> end
>>
>> which compiles just fine, and probably works as intended.  If I include
>> the original method make_el above the new one like this:
>>   method make_el x = new p x
>>   method make_el x = new p2 x
>> Ignoring the warning about overriding methods within the same class, we
>> come to the root of the type problem: make_el must have a type.  After
>> inference completes on the first line, make_el's type is determined to
>> be p.  The second make_el's type must match, but it doesn't.  I don't
>> see a solution for your problem that doesn't involve this kind of manual
>> expansion and removal of duplicate methods, but I'm fairly sure this is
>> the real problem for you.
>>
>> E.
>>
>

--
http://martin.jambon.free.fr


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

* Re: Why can't I call a function over a subclass?
  2007-10-05 15:49               ` Luca de Alfaro
  2007-10-05 16:34                 ` Edgar Friendly
@ 2007-10-05 19:48                 ` Zheng Li
  2007-10-06  1:49                   ` [Caml-list] " Jake Donham
  2007-10-09  4:18                 ` Jacques Garrigue
  2 siblings, 1 reply; 22+ messages in thread
From: Zheng Li @ 2007-10-05 19:48 UTC (permalink / raw)
  To: caml-list

"Luca de Alfaro" <luca@dealfaro.org> writes:
> class p (x: int) = object
>   method plus1 : int = x + 1
> end
>
> class p2 (x: int) = object
>   inherit p x
>   method plus2 : int = x + 2
> end
>
> class r = object (self)
>   val mutable l = []
>   method make_el x = new p x
>   method add (x: int) : unit = l <- (self#make_el x) :: l
>   method length : int = List.length l
>   method total : int = List.fold_left (fun t el -> t + el#plus1) 0 l 
> end
>
> class r2 = object
>   inherit r
>   method make_el x = new p2 x
>   method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l 
> end

I tried it in another way, maybe not the way you expect, but just for your
reference.

<code>
class virtual r = object
  val mutable l = []
  val virtual make_el: int -> #p
  method add x = l <- make_el x ::l
  method length = List.length l
  method total = List.fold_left (fun t el -> t + el#plus1) 0 l
end
class r1 = object inherit r val make_el = new p end
class r2 = object inherit r 
  val make_el = new p2 
  method total2 = List.fold_left (fun t el -> t + el#plus2) 0 l
end
</code>

Note that before you finally provide the virtual classes with a concrete
make_el, you're free to inherit and extend them *arbitrarily*. E.g.

<code>
class virtual r3 = object inherit r
  method total3 = List.fold_left (fun t el -> t + el#plus3) 0 l
end
class virtual r4 = object inherit r3 (* r3 is extensible *)
  method total4 = List.fold_left (fun t el -> t + el#plus4) 0 l
end
</code>

HTH.
-- 
Zheng Li
http://www.pps.jussieu.fr/~li


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

* Re: [Caml-list] Re: Why can't I call a function over a subclass?
  2007-10-05 19:48                 ` Why can't I call a function over a subclass? Zheng Li
@ 2007-10-06  1:49                   ` Jake Donham
  0 siblings, 0 replies; 22+ messages in thread
From: Jake Donham @ 2007-10-06  1:49 UTC (permalink / raw)
  To: caml-list

Hi Luca,

Others have given good replies already but you may find this article helpful:

  http://skydeck.com/blog/programming/ocaml-for-the-recovering-java-programmer-part-1-objects-and-subtyping/

What it comes down to is that in OCaml subsumption (i.e. the whole
idea of object oriented programming) is accomplished using
polymorphism, not implicit coercion.

Jake


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

* Re: [Caml-list] Re: Why can't I call a function over a subclass?
       [not found]                       ` <28fa90930710052153k2128bb63m5132455868eb2008@mail.gmail.com>
@ 2007-10-07 22:19                         ` Martin Jambon
  2007-10-07 22:57                         ` Classes and polymorphism (Re: [Caml-list] Re: Why can't I call a function over a subclass?) Martin Jambon
  1 sibling, 0 replies; 22+ messages in thread
From: Martin Jambon @ 2007-10-07 22:19 UTC (permalink / raw)
  To: Luca de Alfaro; +Cc: caml-list

Luca,

I think what you meant is:

----------
class r (x_init: int) = object
   method get_x : int = x_init
end

let f (r1: r) (r2: r) : bool = (r1#get_x = r2#get_x)

class r' (x_init: int) = object
   inherit r x_init
   method get_xx : int = 2 * x_init
end

let q (r1: r') (r2: r') = f (r1 :> r) (r2 :> r)
--------------

You could also write:

let f r1 r2 : bool = ((r1 :> r)#get_x = (r2 :> r)#get_x)
let q (r1: r') (r2: r') = f r1 r2

I think the second form is nicer, since f is now polymorphic, and accepts 
any object type which is compatible with r, such as r'.


Martin


On Fri, 5 Oct 2007, Luca de Alfaro wrote:

> I am not so used to ":>"... looking at the example I posted, would you be
> able to tell me how to make it type-check by adding ":>"?  This would be
> very much appreciated...
>
> Luca
>
> On 10/5/07, Martin Jambon <martin.jambon@ens-lyon.org> wrote:
>>
>> On Fri, 5 Oct 2007, Luca de Alfaro wrote:
>>
>>> But the larger issue is: when a type is used for an input parameters, as
>> the
>>> type p in:
>>> f : int -> p -> bool
>>> why does the compiler have to complain that p has too many methods?
>>
>> That's your point of view. The compiler complains about different types,
>> but it doesn't know which one is intended:  does one object have
>> too many methods or does the other object miss some methods?
>>
>> With some experience, you will learn that artificially annotating types
>> of objects or polymorphic variants leads to much clearer and earlier error
>> messages.
>>
>> So I would say that using ":>" is a rather mild annoyance, except that you
>> have to learn what it means.
>>
>>
>> Martin
>>
>>
>>> Would it not be possible to make the type checker smarter, and ensure
>> that
>>> when p is an input type, it is ok to have more methods?
>>> And for output types as well, it would seem?
>>> In other words, what is that fundamentally breaks if one were to change
>> the
>>> ocaml type checker in this way?
>>>
>>> Luca
>>>
>>> On 10/5/07, Edgar Friendly <thelema314@gmail.com> wrote:
>>>>
>>>> Luca de Alfaro wrote:
>>>>> Yes, here is some code.  Any help would be very much appreciated.
>>>>> The following fails to type check:
>>>>>
>>>>> class p (x: int) = object
>>>>>   method plus1 : int = x + 1
>>>>> end
>>>>>
>>>>> class p2 (x: int) = object
>>>>>   inherit p x
>>>>>   method plus2 : int = x + 2
>>>>> end
>>>>>
>>>>> class r = object (self)
>>>>>   val mutable l = []
>>>>>   method make_el x = new p x
>>>>>   method add (x: int) : unit = l <- (self#make_el x) :: l
>>>>>   method length : int = List.length l
>>>>>   method total : int = List.fold_left (fun t el -> t + el#plus1) 0 l
>>>>> end
>>>>>
>>>>> class r2 = object
>>>>>   inherit r
>>>>>   method make_el x = new p2 x
>>>>>   method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l
>>>>> end
>>>>>
>>>> if I manually perform the inherit operation by pasting the code from r1
>>>> into r2, I get:
>>>>
>>>> class r2 = object (self)
>>>>   val mutable l = []
>>>>   method make_el x = new p2 x
>>>>   method add (x: int) : unit = l <- (self#make_el x) :: l
>>>>   method length : int = List.length l
>>>>   method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l
>>>> end
>>>>
>>>> which compiles just fine, and probably works as intended.  If I include
>>>> the original method make_el above the new one like this:
>>>>   method make_el x = new p x
>>>>   method make_el x = new p2 x
>>>> Ignoring the warning about overriding methods within the same class, we
>>>> come to the root of the type problem: make_el must have a type.  After
>>>> inference completes on the first line, make_el's type is determined to
>>>> be p.  The second make_el's type must match, but it doesn't.  I don't
>>>> see a solution for your problem that doesn't involve this kind of
>> manual
>>>> expansion and removal of duplicate methods, but I'm fairly sure this is
>>>> the real problem for you.
>>>>
>>>> E.
>>>>
>>>
>>
>> --
>> http://martin.jambon.free.fr
>>
>

--
http://martin.jambon.free.fr


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

* Classes and polymorphism (Re: [Caml-list] Re: Why can't I call a function over a subclass?)
       [not found]                       ` <28fa90930710052153k2128bb63m5132455868eb2008@mail.gmail.com>
  2007-10-07 22:19                         ` Martin Jambon
@ 2007-10-07 22:57                         ` Martin Jambon
  1 sibling, 0 replies; 22+ messages in thread
From: Martin Jambon @ 2007-10-07 22:57 UTC (permalink / raw)
  To: Luca de Alfaro; +Cc: caml-list

On Fri, 5 Oct 2007, Luca de Alfaro wrote:

> I am not so used to ":>"... looking at the example I posted, would you be
> able to tell me how to make it type-check by adding ":>"?  This would be
> very much appreciated...

Ah, sorry, I missed your second problem, which was:
(next time please change the subject line and cc the list)

class p (x: int) = object
   method plus1 : int = x + 1
end

class p2 (x: int) = object
   inherit p x
   method plus2 : int = x + 2
end

class r = object (self)
   val mutable l = []
   method make_el x = new p x
   method add (x: int) : unit = l <- (self#make_el x) :: l
   method length : int = List.length l
   method total : int = List.fold_left (fun t el -> t + el#plus1) 0 l
end

class r2 = object
   inherit r
   method make_el x = new p2 x
   method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l
end



What you're trying to do usually ends up being a nightmare: l would have 
to be polymorphic.
Keeping classes polymorphic is not something practical.
If you inherit an object value such as l, basically it will have one fixed 
type, and that's all.


I find the following guidelines convenient:

Define class types independently from class implementations when you know 
that you will have several classes of the same type. Only use 
monomorphic methods and values.

You may inherit a class from another, and you don't need polymorphic 
classes for this.

You never have to use inheritance.

You don't have to use classes, immediate objects are often sufficient 
(object ... end).

You can inherit and override methods, which is convenient when only a 
small subset of methods differ between two classes. That's when your 
classes are like an evolutionary tree of species. Don't bother when you 
have only 2 or 3 classes.



Martin

--
http://martin.jambon.free.fr


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

* Re: [Caml-list] Re: Why can't I call a function over a subclass?
  2007-10-05 15:49               ` Luca de Alfaro
  2007-10-05 16:34                 ` Edgar Friendly
  2007-10-05 19:48                 ` Why can't I call a function over a subclass? Zheng Li
@ 2007-10-09  4:18                 ` Jacques Garrigue
  2 siblings, 0 replies; 22+ messages in thread
From: Jacques Garrigue @ 2007-10-09  4:18 UTC (permalink / raw)
  To: luca; +Cc: caml-list

From: "Luca de Alfaro" <luca@dealfaro.org>

> Yes, here is some code.  Any help would be very much appreciated.
> The following fails to type check:
> 
> class p (x: int) = object
>   method plus1 : int = x + 1
> end
> 
> class p2 (x: int) = object
>   inherit p x
>   method plus2 : int = x + 2
> end
> 
> class r = object (self)
>   val mutable l = []
>   method make_el x = new p x
>   method add (x: int) : unit = l <- (self#make_el x) :: l
>   method length : int = List.length l
>   method total : int = List.fold_left (fun t el -> t + el#plus1) 0 l
> end
> 
> class r2 = object
>   inherit r
>   method make_el x = new p2 x
>   method total2 : int = List.fold_left (fun t el -> t + el#plus2) 0 l
> end

Zheng Li already provided an answer to your problem. However Zheng's
answer, while doing exactly what you were trying to do, use virtual
value fields, which are a new feature in 3.10.
A more standard way to do this would be to use a private virtual
method, as make_el is the same across all instances of a specific
class.

class virtual r = object (self)
  val mutable l = []
  method private virtual make_el : int -> #p
  method add x = l <- self#make_el x ::l
  method length = List.length l
  method total = List.fold_left (fun t el -> t + el#plus1) 0 l
end
class r1 = object inherit r method make_el = new p end
class r2 = object inherit r 
  method make_el = new p2 
  method total2 = List.fold_left (fun t el -> t + el#plus2) 0 l
end

Practically, these two solutions are equivalent.

Jacques Garrigue


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

end of thread, other threads:[~2007-10-09  4:19 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-10-05  7:48 Why can't I call a function over a subclass? Luca de Alfaro
2007-10-05  8:01 ` [Caml-list] " Florian Hars
2007-10-05  8:08   ` Luca de Alfaro
2007-10-05  8:08     ` Fwd: " Luca de Alfaro
2007-10-05 11:08     ` Vincent Aravantinos
2007-10-05 11:47       ` Christophe Raffalli
2007-10-05 10:30   ` David Teller
2007-10-05 10:53     ` Zheng Li
2007-10-05 14:02       ` [Caml-list] " David Teller
2007-10-05 14:59         ` Luca de Alfaro
2007-10-05 15:12           ` Luca de Alfaro
     [not found]             ` <20071005152130.M41697@cs.unm.edu>
2007-10-05 15:49               ` Luca de Alfaro
2007-10-05 16:34                 ` Edgar Friendly
2007-10-05 17:39                   ` Luca de Alfaro
2007-10-05 17:49                     ` Martin Jambon
     [not found]                       ` <28fa90930710052153k2128bb63m5132455868eb2008@mail.gmail.com>
2007-10-07 22:19                         ` Martin Jambon
2007-10-07 22:57                         ` Classes and polymorphism (Re: [Caml-list] Re: Why can't I call a function over a subclass?) Martin Jambon
2007-10-05 19:48                 ` Why can't I call a function over a subclass? Zheng Li
2007-10-06  1:49                   ` [Caml-list] " Jake Donham
2007-10-09  4:18                 ` Jacques Garrigue
2007-10-05  8:07 ` [Caml-list] " Pietro Abate
2007-10-05 10:55 ` Andrej Bauer

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).