ocaml class with method accepting derived classes

Viewed 123

Consider the following code:

module Proxy = struct
  type 'a t
end

class qObject proxy = object(self : 'self)
  method proxy : 'self Proxy.t = proxy
end

class qWidget proxy = object(self : 'self)
  inherit qObject proxy
  method add : qWidget -> unit = fun w -> ()
  method as_qWidget = (self :> qWidget)
end

class qButton proxy = object(self : 'self)
  inherit qWidget proxy
  method text = "button"
end

let qObject_proxy : qObject Proxy.t = Obj.magic 0
let qWidget_proxy : qWidget Proxy.t = Obj.magic 0
let qButton_proxy : qButton Proxy.t = Obj.magic 0

let qObject = new qObject qObject_proxy
let qWidget = new qWidget qWidget_proxy
let qButton = new qButton qButton_proxy

let () = qWidget#add qWidget
let () = qWidget#add qButton#as_qWidget

That code is well typed and compiles. But qButton must be manually cast to qWidget which I want to eliminate. I want qWidget#add to accept another qWidget or any derived class (like qButton). I thought #qWidget would be the right type for that but that doesn't work:

class qWidget proxy = object(self : 'self)
  inherit qObject proxy
  method add : #qWidget -> unit = fun w -> ()
end

Error: Some type variables are unbound in this type: ...
The method add has type 'c -> unit where 'c is unbound

and

class qWidget proxy = object(self : 'self)
  inherit qObject proxy
  method add : 'a . (#qWidget as 'a) -> unit = fun w -> ()
end

Error: The universal type variable 'a cannot be generalized:
it escapes its scope.

Is there some way around this that I'm not seeing?

1 Answers
Related