Google Groups không còn hỗ trợ đăng ký sử dụng hoặc đăng nội dung mới trên Usenet. Bạn vẫn có thể xem nội dung cũ.

[Caml-list] troubles with polymorphic variant in class

0 lượt xem
Chuyển tới thư đầu tiên chưa đọc

François-XavierHOUARD

chưa đọc,
12:09:28 13 thg 6, 200413/6/04
đến caml...@inria.fr
English version:

Hi everyone

I'm working on an ocaml GUI library -more information about it later, on
the list ;)

I'm now working on an introspecting side of this GUI library; in a GUI,
every composant can have some child, and have a father.
The choice I'v made is to have a class for every type of composant, and
an object for every composant, for example, I have a window class, a
frame class (inheriting window), a button class, a panel class, etc.

So, as every composant can have different type of father, every object
is parametrized by the type of his father, for example, a button in a
panel in a window is, for the moment, typed as
window panel button
as the button class looks like that:
class ['a] button (father:'a)
....
and the panel too,etc

I find it nice, cause every widget has got his "genealogic tree" in his
type.

What I wan't now is to store every widget child in a list.
as every child should be from a different type, and as I wan't the user
to be able to add his own widget-class later, I first thought of the use
of polymorphic variant, like that:

class ['a] button (father:'a) =
object(self)
val f = father
val mutable childs = [`Whatever]
method add_child (x) = childs <- x::childs
method get_variant = `A self
end;;

but caml tells me that:
The method add_child has type ([> `Whatever ] as 'a) -> unit where 'a
is unbound

This could be solved by adding a 'b parameter to my class:

class ['a, 'b] button (father:'a) =
object(self)
val f = father
val mutable childs = [`Whatever]
method add_child (x:'b) = childs <- x::childs
method get_variant :'b = `A self
end;;

but this may make my class type unreadable:

[> 'Whatever | `Window of window ] window [> 'Whatever | `Window of
window | `Panel of panel ] panel [> 'Whatever | `Window of window |
`Panel of panel | `Button of button ] button

So, I have 2 questions:
_ Why should an open type as [>`Whatever] be parameter of a class ?? As
far as I know it, [>`Whatever] is equivalent to [>`Whatever | `Foo of
bar | `Foobar of foobar ], isn't it ?? so what problem would it make for
the inheritage stuff (which are the reason of the use of parameter)
_Is there another way to make it ??? (yes, i know coca-ml, but, another
way ??)

Thanks for all

FX Houard

Version Française:

Bonjour tous le monde

je travail sur une librairie de GUI en Caml -plus d'infos plus tard sur
la liste ;)

Je travail sur la partie introspective de cette librairie de GUI; dans
une GUI, chaque composant peut avoir des enfants, et a un père.

Le choix que j'ai fais est d'avoir une class pour chaque type de
composant, et un objet pour chaque composant; par exemple, j'ai une
class de "fenetre", in class de "frame", une de panel, une de bouton,
etc...

Donc, comme chaque composant peut avoir un père de type différent,
chaque objet est paramétré par le type de son père, par exeample, u=
n
bouton dans un panel dans une fenetre a le type:
window panel button
comme la classe bouton ressemble à ça:
class ['a] button (father:'a)
....

et la classe panel aussi, etc..

je trouve ça plutôt chouette, puisque chaque widget a son arbre
généalogique dans son type

Ce que je voudrais maintenant, c'est stocker les enfants de chaque
widget dans une liste.
Comme chaque enfant peut être d'un type différent, et comme je veux q=
ue
l'utilisateur puisse rajouter ses propres classes de widget, j'ai
d'abord pensé aux variants polymorphes:

class ['a] button (father:'a) =
object(self)
val f = father
val mutable childs = [`Whatever]
method add_child (x) = childs <- x::childs
method get_variant = `A self
end;;

Mais caml me réponds
The method add_child has type ([> `Whatever ] as 'a) -> unit where 'a
is unbound (je vais pas traduire ça, non plus !!;)

Celà pourrait être résolu en ajoutant le paramètre 'b à ma clas=
se:

class ['a, 'b] button (father:'a) =
object(self)
val f = father
val mutable childs = [`Whatever]
method add_child (x:'b) = childs <- x::childs
method get_variant :'b = `A self
end;;

Mais ça devrait rendre mes types illisibles:

[> 'Whatever | `Window of window ] window [> 'Whatever | `Window of
window | `Panel of panel ] panel [> 'Whatever | `Window of window |
`Panel of panel | `Button of button ] button

J'ai donc 2 questions:
_Pourquoi un type ouvert comme [>`Whatever] devrait être un paramètre=
de
ma classe ? d'autant que je le sache, [>`Whatever] est équivalent à
[>`Whatever | `Foo of bar | `Foobar of foobar ], non ??
Alors quel problème pour l'héritage (qui est la raison de l'utilisati=
on
de paramètre) celà ferait il ??
_Y aurait il une autre façon de faire ce que je veux (je connais certe
coca-ml, mais, une autre façon existe peut être) ?

Merci pour tous

FX Houard

-------------------
To unsubscribe, mail caml-lis...@inria.fr Archives: http://caml.inr=
ia.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

skaller

chưa đọc,
14:03:32 13 thg 6, 200413/6/04
đến Id...@iname.com, caml-list
On Mon, 2004-06-14 at 02:05, François-Xavier HOUARD wrote:

> The method add_child has type ([> `Whatever ] as 'a) -> unit where 'a
> is unbound

> _Is there another way to make it ???

The notation [> `X] does not denote a type, but a family
of types (all types containing variant `X). Alternatively
you might say it is a type constraint.

But a list must have elements of a definite type.
You can define the type as for ordinary variants:

type widget = [ `Whatever | `Window of window | `Button of button]

and now make a widget list.

Unfortunately, you cannot add child widgets to a button
like this:

class button = object
val mutable (childs:widget list)
method add_child x = childs <- x::childs
end

because button isn't defined yet .. and neither
is window... so you can't define widget.

Unfortunately the obvious way to fix this doesn't
work due to a syntactic problem in Ocaml:

type widget = ...
and class window = ...
and class button = ...

is what you need: mutual recursion. But it isn't allowed
to mutually recurse types and classes (not even class types).

So a direct solution is unfortunately impossible.
You must add a type parameter to each class like this:

class ['w] button' = ... (childs: 'w list)
class ['w] window' = .. .(childs: 'w list) ...

and now you can define:

type 'w widget' = [`Window of ['w] window' | ...

Because these things all use a parameter,
they can all be defined without any mutual
recursion. So now you do this:

(* fixpoint *)
type widget = 'w widget' as 'w

which effectively solves the type equation
'w = 'w widget (and names the result widget).
Now define non-polymorphic classes:

class button = [widget] button'
class window = [widget] window'

This is not so bad for a single parameter 'w.
For multiple parameters the notation soon becomes
too unwieldy to be practical.

--
John Skaller, mailto:ska...@users.sf.net
voice: 061-2-9660-0850,
snail: PO BOX 401 Glebe NSW 2037 Australia
Checkout the Felix programming language http://felix.sf.net

Richard Jones

chưa đọc,
05:39:25 14 thg 6, 200414/6/04
đến caml...@inria.fr
On Sun, Jun 13, 2004 at 06:05:57PM +0200, François-Xavier HOUARD wrote:
> So, as every composant can have different type of father, every object
> is parametrized by the type of his father, for example, a button in a
> panel in a window is, for the moment, typed as
> window panel button
> as the button class looks like that:
> class ['a] button (father:'a)
> ....
> and the panel too,etc
>
> I find it nice, cause every widget has got his "genealogic tree" in his
> type.

I'm probably missing something here, but what's wrong with having
every widget just contain an ordinary data item / method pointing to
the parent? eg. button#parent == panel ?

Rich.

--
Richard Jones. http://www.annexia.org/ http://www.j-london.com/
Merjis Ltd. http://www.merjis.com/ - improving website return on investme=
nt
C2LIB is a library of basic Perl/STL-like types for C. Vectors, hashes,
trees, string funcs, pool allocator: http://www.annexia.org/freeware/c2li=
b/

François-XavierHOUARD

chưa đọc,
06:00:46 14 thg 6, 200414/6/04
đến caml...@inria.fr
Le dim 13/06/2004 à 19:59, skaller a écrit :

> (* fixpoint *)
> type widget = 'w widget' as 'w
>
> which effectively solves the type equation
> 'w = 'w widget (and names the result widget).
> Now define non-polymorphic classes:
>
> class button = [widget] button'
> class window = [widget] window'
>
> This is not so bad for a single parameter 'w.
> For multiple parameters the notation soon becomes
> too unwieldy to be practical.

But the answer you gave me, which I find quite nice, don't allow my user
to add his own class....
I could do the stuff with a parametrized module (the parameter given by
the user would contain the variant used in the program... Including the
ones of my library!!), or, even uglier, use a close variant in my
module, which would be like:
[ Window of window | Frame of frame | User_variant of 'a ]

And 'a, the parameter of the module, given by the user, would also be a
variant...

module SillyModule =
struct
type t = [ MyWindow of myWindow | MyText of myText ];;
end
;;
module myGui = Gui (SillyModule);;
let a = new Window;;
let x = new myText a;;
let l = a#get_child in
match l with
h::t -> (match h with
myGui.User_variant v ->
( match v with
MyText t -> .......
| _ ->
)
| _ -> raise Not_found
)
....


Who the hell would use this ???

So, if I can't find a better solution, i could still try to find a
sado-m(l)asochist mailing list, to find potential users !

;))


Let's be more serious. What you said is fine, but, please, tell me there
is an easier solution to make it work with user defined class...
Please....

Thanks for all

FX Houard, desperate to find an elegant and extensible solution to his
problem... And attracted by the dark-dynamic-typed side of coca-ml.

Damien Doligez

chưa đọc,
06:00:48 14 thg 6, 200414/6/04
đến Liste Caml
On Jun 14, 2004, at 11:29, François-Xavier HOUARD wrote:

> let l = a#get_child in
> match l with
> h::t -> (match h with
> myGui.User_variant v ->
> ( match v with
> MyText t -> .......
> | _ ->
> )
> | _ -> raise Not_found
> )
> ....
>
>
> Who the hell would use this ???

You don't really need to obfuscate your own code:

match a#get_child with
| MyGui.User_variant (MyText t) :: tt -> .......
| _ -> raise Not_found
....

-- Damien

-------------------
To unsubscribe, mail caml-lis...@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/

nakata keiko

chưa đọc,
10:51:12 14 thg 6, 200414/6/04
đến Id...@iname.com, caml...@inria.fr, ke...@kaba.or.jp
I hope this would be of some help.

module type Ct = sig type t end

module type Crec =
sig
module T : Ct
class button : object method add_child : T.t -> unit end
end

module COt(Crec : Crec) =
struct type t = [`Whatever|`Button of Crec.button]
end

module CO(Crec : Crec) =
struct
module T = COt(Crec)
class button =
object
val mutable children : T.t list = [`Whatever]
method add_child x = children <- x::children
end
end
module rec X : (Crec with module T = COt(X)) = CO(X)

As I done, you can specify the type of elements of the list "children"
inside "COt".
The above code is taken from
http://caml.inria.fr/archives/200403/msg00344.html

with best regards.

-------------------
To unsubscribe, mail caml-lis...@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/

skaller

chưa đọc,
11:54:03 14 thg 6, 200414/6/04
đến Id...@iname.com, caml-list
On Mon, 2004-06-14 at 19:29, François-Xavier HOUARD wrote:

> But the answer you gave me, which I find quite nice, don't allow my use=


r
> to add his own class....

They would have to edit the module to do it, but they
can do it.

Here is another solution: visitor pattern.

class 'w window = object (self)
val mutable childs: 'w list
...
method iter (f:'w -> unit) =
List.iter f childs
end

... user now can write:

type 'w mywidgets' = [`A of 'w a_kind' | `B of 'w b_kind' .. ]

class ['w] a_kind' = object .....
class a_kind = widget a_kind' ...

etc etc as before. Now the *user* must unify all the types
with a variant, but the class doesn't need to know
what is is until it is instantiated.

One way or the other there is no alternative to unifying
all the widget types with a sum (variant) or an abstraction
(class supertypes) or both.

Typical GUI like GTK do both (there are run time
tests for kinds of widgets, so you can do button
specific things on any kind of button etc).

--
John Skaller, mailto:ska...@users.sf.net
voice: 061-2-9660-0850,
snail: PO BOX 401 Glebe NSW 2037 Australia
Checkout the Felix programming language http://felix.sf.net

-------------------

0 tin nhắn mới