Reputation: 12332
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?
Upvotes: 4
Views: 132
Reputation: 12332
I found a way around this. The trick is that add does not need an object that is derived from qWidget but only an object that can cast itself to qWidget, as in has the as_qWidget method. That way the necessary cast to qWidget can be pulled into the method without needing the bothersome #qWidget.
class qWidget proxy = object(self : 'self)
inherit qObject proxy
method add : 'a . (<as_qWidget : qWidget; ..> as 'a) -> unit
= fun w -> let w = w#as_qWidget in ()
method as_qWidget = (self :> qWidget)
end
Upvotes: 5