caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Yet another question about insufficient polymorphism
@ 2008-03-12 19:34 Richard Jones
       [not found] ` <95513600803121319y508923a1vb36ac59c21e93f5b@mail.gmail.com>
  2008-03-18 10:56 ` Richard Jones
  0 siblings, 2 replies; 4+ messages in thread
From: Richard Jones @ 2008-03-12 19:34 UTC (permalink / raw)
  To: caml-list

This is yet another "insufficient polymorphism" question that I just
can't work out ...

I have a signature like this:

newt.mli:

  type 'a component

  val form_add_component :
    [> `Form ] component -> [> `Component ] component -> unit
  val form_add_components :
    [> `Form ] component -> [> `Component ] component list -> unit

An implementation like this:

newt.ml:

  type 'a component = {
    co : newtComponent;
    mutable in_form : bool;
  }

  let form_add_component form co =
    if co.in_form then failwith "component can only be added to a single form";
    newtFormAddComponent form.co co.co;
    co.in_form <- true

  let form_add_components form components =
    List.iter (fun co -> form_add_component form co) components

And my test program is:

04_form.ml:

  let text = textbox 1 1 15 5 [WRAP; SCROLL] in
  textbox_set_text text "This is some text in a reflowed text box.";
  let b1 = button 5 8 "  OK  " in
  let b2 = button 5 13 "Cancel" in
  let form = form None None [] in
  form_add_components form [text; b1; b2];
                                  ^^

File "examples/04_form.ml", line 17, characters 33-35:
This expression has type [ `Button | `Component ] Newt.component
but is here used with type [ `Component | `Textbox ] Newt.component
The second variant type does not allow tag(s) `Button
make: *** [examples/04_form.cmo] Error 2

This all worked until I added the newt.mli file.  (I previously just
had a newt.ml file, with explicit types on all the functions).

Rich.

-- 
Richard Jones
Red Hat


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

* Re: [Caml-list] Yet another question about insufficient polymorphism
       [not found]     ` <95513600803121457l17e90817y54d419784462ae85@mail.gmail.com>
@ 2008-03-12 22:13       ` Richard Jones
  2008-03-12 22:56         ` Olivier Andrieu
  0 siblings, 1 reply; 4+ messages in thread
From: Richard Jones @ 2008-03-12 22:13 UTC (permalink / raw)
  To: Olivier Andrieu; +Cc: caml-list

[Hope you don't mind this but I've CC'd back to caml-list ...]

On Wed, Mar 12, 2008 at 10:57:46PM +0100, Olivier Andrieu wrote:
> On Wed, Mar 12, 2008 at 9:59 PM, Richard Jones <rich@annexia.org> wrote:
> > On Wed, Mar 12, 2008 at 09:19:32PM +0100, Olivier Andrieu wrote:
> >  > aren't you missing a variance annotation ? like :
> >  >
> >  > type -'a component
> >
> >  I don't know because no one has ever been able to explain covariance &
> >  contravariance to me in a comprehensible way !
> 
> there's this post where I tried to explain that to someone:
> http://groups.google.com/group/fa.caml/msg/584ea2139b69f0ed
> 
> >  I added the '-' but it doesn't appear to have fixed the problem
> >  unfortunately.
> 
> You'll need it anyway I think :)
> What's the type of your functions that create components ? (textbox
> and button ?)

val button : int -> int -> string -> [ `Button | `Component ] component

val textbox : int -> int -> int -> int -> flag list ->
    [ `Component | `Textbox ] component

> >  Someone mentioned that it might be because when I added the signature,
> >  the type became abstract (before, the implementation of the type was
> >  exposed).  I can't make that work either though, but maybe because my
> >  type is slightly different than it was before ...
> 
> You'll probably have to add some coercions , like:
> 
>   let as_co c = (c :> [`Component] component)
> 
> and then
> 
>   form_add_components form [as_co text; as_co b1; as_co b2];

Right, this is very confusing.  Adding the -'a annotation:

  type -'a component

and:

  let as_co c = (c :> [`Component] component) in
  form_add_components form [as_co text; as_co b1; as_co b2];              

works.

However omitting the minus in "type -'a ..." breaks it, and changing
the list to:

  ([text; b1; b2] :> [`Component] component list)

doesn't work either.

I guess I'll need to read about co-/contra-variance.

Rich.

-- 
Richard Jones
Red Hat


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

* Re: [Caml-list] Yet another question about insufficient polymorphism
  2008-03-12 22:13       ` [Caml-list] " Richard Jones
@ 2008-03-12 22:56         ` Olivier Andrieu
  0 siblings, 0 replies; 4+ messages in thread
From: Olivier Andrieu @ 2008-03-12 22:56 UTC (permalink / raw)
  To: Richard Jones; +Cc: caml-list

On Wed, Mar 12, 2008 at 11:13 PM, Richard Jones <rich@annexia.org> wrote:
> [Hope you don't mind this but I've CC'd back to caml-list ...]
>
>
>  On Wed, Mar 12, 2008 at 10:57:46PM +0100, Olivier Andrieu wrote:
>  > On Wed, Mar 12, 2008 at 9:59 PM, Richard Jones <rich@annexia.org> wrote:
>  > > On Wed, Mar 12, 2008 at 09:19:32PM +0100, Olivier Andrieu wrote:
>  > >  > aren't you missing a variance annotation ? like :
>  > >  >
>  > >  > type -'a component
>  > >
>  > >  I don't know because no one has ever been able to explain covariance &
>  > >  contravariance to me in a comprehensible way !
>  >
>  > there's this post where I tried to explain that to someone:
>  > http://groups.google.com/group/fa.caml/msg/584ea2139b69f0ed
>  >
>  > >  I added the '-' but it doesn't appear to have fixed the problem
>  > >  unfortunately.
>  >
>  > You'll need it anyway I think :)
>  > What's the type of your functions that create components ? (textbox
>  > and button ?)
>
>  val button : int -> int -> string -> [ `Button | `Component ] component
>
>  val textbox : int -> int -> int -> int -> flag list ->
>     [ `Component | `Textbox ] component
>
>
>  > >  Someone mentioned that it might be because when I added the signature,
>  > >  the type became abstract (before, the implementation of the type was
>  > >  exposed).  I can't make that work either though, but maybe because my
>  > >  type is slightly different than it was before ...
>  >
>  > You'll probably have to add some coercions , like:
>  >
>  >   let as_co c = (c :> [`Component] component)
>  >
>  > and then
>  >
>  >   form_add_components form [as_co text; as_co b1; as_co b2];
>
>  Right, this is very confusing.  Adding the -'a annotation:
>
>   type -'a component
>
>  and:
>
>   let as_co c = (c :> [`Component] component) in
>
>   form_add_components form [as_co text; as_co b1; as_co b2];
>
>  works.
>
>  However omitting the minus in "type -'a ..." breaks it,

Right. The '-' annotation says the parameter is contravariant which means that
with a coercion you can "loose" some of the variants. Without the
annotation the coercion would fail.

> and changing the list to:
>
>   ([text; b1; b2] :> [`Component] component list)
>
>  doesn't work either.

Yes because it doesn't even get to the coercion, it fails while trying
to build the list:
text and b1 have incompatible types.

In the end, the easiest way to write this is probably to avoid the
list altogether:

  form_add_component form text ;
  form_add_component form b1 ;
  form_add_component form b2 ;

-- 
  Olivier


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

* Re: [Caml-list] Yet another question about insufficient polymorphism
  2008-03-12 19:34 Yet another question about insufficient polymorphism Richard Jones
       [not found] ` <95513600803121319y508923a1vb36ac59c21e93f5b@mail.gmail.com>
@ 2008-03-18 10:56 ` Richard Jones
  1 sibling, 0 replies; 4+ messages in thread
From: Richard Jones @ 2008-03-18 10:56 UTC (permalink / raw)
  To: caml-list

On Wed, Mar 12, 2008 at 07:34:32PM +0000, Richard Jones wrote:
> I have a signature like this:
> 
> newt.mli:
> 
>   type 'a component
> 
>   val form_add_component :
>     [> `Form ] component -> [> `Component ] component -> unit
>   val form_add_components :
>     [> `Form ] component -> [> `Component ] component list -> unit
> 
> An implementation like this:
> 
> newt.ml:
> 
>   type 'a component = {
>     co : newtComponent;
>     mutable in_form : bool;
>   }

[...]

> 04_form.ml:
> 
>   let text = textbox 1 1 15 5 [WRAP; SCROLL] in
>   textbox_set_text text "This is some text in a reflowed text box.";
>   let b1 = button 5 8 "  OK  " in
>   let b2 = button 5 13 "Cancel" in
>   let form = form None None [] in
>   form_add_components form [text; b1; b2];
>                                   ^^

The answer to this, pointed out to me by milanst, is to write the type
like this:

  type _component = {
    co : newtComponent;
    mutable in_form : bool;
  }
  type 'a component = _component

which works as expected, without any "casts" needed on the call to
form_add_components.

Rich.

-- 
Richard Jones
Red Hat


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

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

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-03-12 19:34 Yet another question about insufficient polymorphism Richard Jones
     [not found] ` <95513600803121319y508923a1vb36ac59c21e93f5b@mail.gmail.com>
     [not found]   ` <20080312205911.GA14545@annexia.org>
     [not found]     ` <95513600803121457l17e90817y54d419784462ae85@mail.gmail.com>
2008-03-12 22:13       ` [Caml-list] " Richard Jones
2008-03-12 22:56         ` Olivier Andrieu
2008-03-18 10:56 ` Richard Jones

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