caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] A confusing example with modules and polymorphic variants
@ 2012-10-19 21:13 Yaron Minsky
  0 siblings, 0 replies; 5+ messages in thread
From: Yaron Minsky @ 2012-10-19 21:13 UTC (permalink / raw)
  To: caml-list



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

* Re: [Caml-list] A confusing example with modules and polymorphic variants
  2012-10-19 22:10 ` Jeremy Yallop
  2012-10-20  1:34   ` Yaron Minsky
@ 2012-10-20  9:16   ` Gabriel Scherer
  1 sibling, 0 replies; 5+ messages in thread
From: Gabriel Scherer @ 2012-10-20  9:16 UTC (permalink / raw)
  To: Jeremy Yallop
  Cc: Yaron Minsky, caml-list, Stephen Weeks, David Powers, Nathan Linger

> I don't see how to make that work in your case, though, because of the nature
> of the polymorphism -- i.e. it's based on a row variable rather than a
> standard type variable, and there isn't any syntax for quantifying it.

You can capture the whole type "as" the polymorphic variable.

  type s = { z : 'a . [< `Foo ] as 'a }

  module type S = sig
    val z : [< `Foo ]
  end

  let f s =
    let module M : S = struct
      let z = s.z
    end in ()

This is essentially the same as your solution, using a polymorphic
field in a record instead of a polymorphic structure item in a
first-class module. I'm not exactly sure if/why this would solve or
not Yaron's problem, but in any regard I would consider the two
solutions equivalent.

On Sat, Oct 20, 2012 at 12:10 AM, Jeremy Yallop <yallop@gmail.com> wrote:
> On 19 October 2012 22:18, Yaron Minsky <yminsky@janestreet.com> wrote:
>> We've been running into some troubles with polymorphic variants,
>> modules, and the value restriction, that we're not quite able to
>> unravel.  Here's a stripped down version of the problem.
>>
>>     module type S = sig
>>       val z : [< `Foo ]
>>     end
>>
>>     let f z =
>>       let module M : S = struct let z = z end in ()
>
> I believe the problem here is the monomorphic parameter restriction: the type
> of S requires the field z to be polymorphic, but type inference only assigns
> monomorhpic types to function parameters.  That is, your example doesn't type
> check for essentially the same reason that the following code doesn't type
> check:
>
>     type s = {
>       z : 'a. 'a -> 'a
>     }
>
>     let f z =
>       let s = {
>         z = z
>       } in
>       ()
>
> One way to work around the monomorphic parameter assumption is to wrap the
> parameter in a record with a polymorphic field.
>
>     type z_type = { field : 'a. 'a -> 'a}
>
>     let f z =
>       let s = {
>         z = z.field
>       } in
>       ()
>
> The parameter is still assigned a monomorphic type (z_type), but the projected
> field is polymorphic, as required.
>
> I don't see how to make that work in your case, though, because of the nature
> of the polymorphism -- i.e. it's based on a row variable rather than a
> standard type variable, and there isn't any syntax for quantifying it.
>
> However, you *can* modify your example so that it passes type checking by
> wrapping the argument in a first-class module, since module fields can be
> row-polymorphic.  The easiest way in the cut-down example is to reuse the
> signature you already have:
>
>     module type S = sig
>       val z : [< `Foo ]
>     end
>
>     let f (module Z : S) =
>       let module M : S =
>           struct
>             let z = Z.z
>           end
>       in ()
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa.inria.fr/sympa/arc/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs

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

* Re: [Caml-list] A confusing example with modules and polymorphic variants
  2012-10-19 22:10 ` Jeremy Yallop
@ 2012-10-20  1:34   ` Yaron Minsky
  2012-10-20  9:16   ` Gabriel Scherer
  1 sibling, 0 replies; 5+ messages in thread
From: Yaron Minsky @ 2012-10-20  1:34 UTC (permalink / raw)
  To: Jeremy Yallop; +Cc: caml-list, Stephen Weeks, David Powers, Nathan Linger

Thanks!  That all makes perfect sense, now that you say it.  Not sure
why it was so hard for me to figure it out on my own.

One interesting bit is that a very similar example can be made to work
without resorting to these kinds of tricks.  In particular, if we
change the [< `Foo] to [> `Foo], then, we can get the polymorphism we
need back by using a cast:

    module type S = sig
      val z : [> `Foo ]
    end

    let f z =
      let module M : S = struct
        let z = (z : [`Foo] :> [> `Foo])
      end in
      ()

But this doesn't really help in the case I'm after.

y


On Fri, Oct 19, 2012 at 6:10 PM, Jeremy Yallop <yallop@gmail.com> wrote:
> On 19 October 2012 22:18, Yaron Minsky <yminsky@janestreet.com> wrote:
>> We've been running into some troubles with polymorphic variants,
>> modules, and the value restriction, that we're not quite able to
>> unravel.  Here's a stripped down version of the problem.
>>
>>     module type S = sig
>>       val z : [< `Foo ]
>>     end
>>
>>     let f z =
>>       let module M : S = struct let z = z end in ()
>
> I believe the problem here is the monomorphic parameter restriction: the type
> of S requires the field z to be polymorphic, but type inference only assigns
> monomorhpic types to function parameters.  That is, your example doesn't type
> check for essentially the same reason that the following code doesn't type
> check:
>
>     type s = {
>       z : 'a. 'a -> 'a
>     }
>
>     let f z =
>       let s = {
>         z = z
>       } in
>       ()
>
> One way to work around the monomorphic parameter assumption is to wrap the
> parameter in a record with a polymorphic field.
>
>     type z_type = { field : 'a. 'a -> 'a}
>
>     let f z =
>       let s = {
>         z = z.field
>       } in
>       ()
>
> The parameter is still assigned a monomorphic type (z_type), but the projected
> field is polymorphic, as required.
>
> I don't see how to make that work in your case, though, because of the nature
> of the polymorphism -- i.e. it's based on a row variable rather than a
> standard type variable, and there isn't any syntax for quantifying it.
>
> However, you *can* modify your example so that it passes type checking by
> wrapping the argument in a first-class module, since module fields can be
> row-polymorphic.  The easiest way in the cut-down example is to reuse the
> signature you already have:
>
>     module type S = sig
>       val z : [< `Foo ]
>     end
>
>     let f (module Z : S) =
>       let module M : S =
>           struct
>             let z = Z.z
>           end
>       in ()

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

* Re: [Caml-list] A confusing example with modules and polymorphic variants
  2012-10-19 21:18 Yaron Minsky
@ 2012-10-19 22:10 ` Jeremy Yallop
  2012-10-20  1:34   ` Yaron Minsky
  2012-10-20  9:16   ` Gabriel Scherer
  0 siblings, 2 replies; 5+ messages in thread
From: Jeremy Yallop @ 2012-10-19 22:10 UTC (permalink / raw)
  To: Yaron Minsky; +Cc: caml-list, Stephen Weeks, David Powers, Nathan Linger

On 19 October 2012 22:18, Yaron Minsky <yminsky@janestreet.com> wrote:
> We've been running into some troubles with polymorphic variants,
> modules, and the value restriction, that we're not quite able to
> unravel.  Here's a stripped down version of the problem.
>
>     module type S = sig
>       val z : [< `Foo ]
>     end
>
>     let f z =
>       let module M : S = struct let z = z end in ()

I believe the problem here is the monomorphic parameter restriction: the type
of S requires the field z to be polymorphic, but type inference only assigns
monomorhpic types to function parameters.  That is, your example doesn't type
check for essentially the same reason that the following code doesn't type
check:

    type s = {
      z : 'a. 'a -> 'a
    }

    let f z =
      let s = {
        z = z
      } in
      ()

One way to work around the monomorphic parameter assumption is to wrap the
parameter in a record with a polymorphic field.

    type z_type = { field : 'a. 'a -> 'a}

    let f z =
      let s = {
        z = z.field
      } in
      ()

The parameter is still assigned a monomorphic type (z_type), but the projected
field is polymorphic, as required.

I don't see how to make that work in your case, though, because of the nature
of the polymorphism -- i.e. it's based on a row variable rather than a
standard type variable, and there isn't any syntax for quantifying it.

However, you *can* modify your example so that it passes type checking by
wrapping the argument in a first-class module, since module fields can be
row-polymorphic.  The easiest way in the cut-down example is to reuse the
signature you already have:

    module type S = sig
      val z : [< `Foo ]
    end

    let f (module Z : S) =
      let module M : S =
          struct
            let z = Z.z
          end
      in ()

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

* [Caml-list] A confusing example with modules and polymorphic variants
@ 2012-10-19 21:18 Yaron Minsky
  2012-10-19 22:10 ` Jeremy Yallop
  0 siblings, 1 reply; 5+ messages in thread
From: Yaron Minsky @ 2012-10-19 21:18 UTC (permalink / raw)
  To: caml-list; +Cc: Stephen Weeks, David Powers, Nathan Linger

Sorry for the previous incomplete message.  Over-eager return key.

We've been running into some troubles with polymorphic variants,
modules, and the value restriction, that we're not quite able to
unravel.  Here's a stripped down version of the problem.

    module type S = sig
      val z : [< `Foo ]
    end

    let f z =
      let module M : S = struct let z = z end in ()

Roughly speaking, we have a module signature S with a value that's a
polymorphic variant type that is not exact (i.e., has some
polymorphism in it.)

The function f then tries to construct a module of that type, by
taking the input value and stuffing it into a locally defined module.
When we do this, however, we're hit by a non-generalizable value
complaint.

    Modules do not match: sig val z : '_a end is not included in S
    Values do not match: val z : '_a is not included in val z : [< `Foo ]
    File "z.ml", line 2, characters 2-19: Expected declaration
    File "z.ml", line 7, characters 8-9: Actual declaration

Any thoughts on why this doesn't work, and how one could get it to?

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

end of thread, other threads:[~2012-10-20  9:16 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-19 21:13 [Caml-list] A confusing example with modules and polymorphic variants Yaron Minsky
2012-10-19 21:18 Yaron Minsky
2012-10-19 22:10 ` Jeremy Yallop
2012-10-20  1:34   ` Yaron Minsky
2012-10-20  9:16   ` Gabriel Scherer

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