caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Initialization of a polymorphic field in a record
@ 2012-07-03 12:18 Jean-Louis Giavitto
  2012-07-03 12:25 ` Philippe Veber
  0 siblings, 1 reply; 4+ messages in thread
From: Jean-Louis Giavitto @ 2012-07-03 12:18 UTC (permalink / raw)
  To: caml-list

Hello.

I am trying to build a record with a polymorphic field and I am unable 
to initialize this field. The problem can be summarized as follow. The 
following definitions works well:

    type t = { check : 'a. 'a -> bool }

    let return_true _ = true

    let make1 () = { check = return_true; }

But this definition raises an error:

    let make2 f = { check = f; }

with the message:

   Error: This field value has type 'a -> bool which is less general than
          'b. 'b -> bool

Note that

    let return_false _ = true

    let make3 c = { check = if c then return_false else return_true; }

is working but that

    let g c = if c then return_false else return_true
    let make4 c = { check = g c; }

raises the same error message. Making explicit the argument of make does 
not helps:

   let make5 f = { check = f; }
   in make5 return_true

(same error message). And making explicit the type of make does not help 
neither:

   let make6 : 'a. ('a -> bool) -> t
   = function f -> { check = f; }

(same error message).



Do you have an idea how I can specify a function similar to make to buid 
a record of type t?

In the real life, the argument f will be the result of a computation and 
instead of a simple signature 'a -> bool, I must deal with a signature

    'a 'b. (('b) #SomeClass as 'a) * 'b -> bool


Thanks for your advice,
Jean-Louis Giavitto.

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

* Re: [Caml-list] Initialization of a polymorphic field in a record
  2012-07-03 12:18 [Caml-list] Initialization of a polymorphic field in a record Jean-Louis Giavitto
@ 2012-07-03 12:25 ` Philippe Veber
  2012-07-03 12:33   ` Jonathan Protzenko
  0 siblings, 1 reply; 4+ messages in thread
From: Philippe Veber @ 2012-07-03 12:25 UTC (permalink / raw)
  To: jean-louis.giavitto; +Cc: caml-list

[-- Attachment #1: Type: text/plain, Size: 2175 bytes --]

Hi,

how about that:

# type t = { check : 'a. 'a -> bool
};;
type t = { check : 'a. 'a -> bool;
}

# let return_true : 'a. 'a -> bool = fun _ ->
true;;
val return_true : 'a -> bool =
<fun>

# let make1 () = { check = return_true;
};;
val make1 : unit -> t =
<fun>

cheers,
  Philippe.


2012/7/3 Jean-Louis Giavitto <jean-louis.giavitto@ircam.fr>

> Hello.
>
> I am trying to build a record with a polymorphic field and I am unable to
> initialize this field. The problem can be summarized as follow. The
> following definitions works well:
>
>    type t = { check : 'a. 'a -> bool }
>
>    let return_true _ = true
>
>    let make1 () = { check = return_true; }
>
> But this definition raises an error:
>
>    let make2 f = { check = f; }
>
> with the message:
>
>   Error: This field value has type 'a -> bool which is less general than
>          'b. 'b -> bool
>
> Note that
>
>    let return_false _ = true
>
>    let make3 c = { check = if c then return_false else return_true; }
>
> is working but that
>
>    let g c = if c then return_false else return_true
>    let make4 c = { check = g c; }
>
> raises the same error message. Making explicit the argument of make does
> not helps:
>
>   let make5 f = { check = f; }
>   in make5 return_true
>
> (same error message). And making explicit the type of make does not help
> neither:
>
>   let make6 : 'a. ('a -> bool) -> t
>   = function f -> { check = f; }
>
> (same error message).
>
>
>
> Do you have an idea how I can specify a function similar to make to buid a
> record of type t?
>
> In the real life, the argument f will be the result of a computation and
> instead of a simple signature 'a -> bool, I must deal with a signature
>
>    'a 'b. (('b) #SomeClass as 'a) * 'b -> bool
>
>
> Thanks for your advice,
> Jean-Louis Giavitto.
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/**wws/info/caml-list<https://sympa-roc.inria.fr/wws/info/caml-list>
> Beginner's list: http://groups.yahoo.com/group/**ocaml_beginners<http://groups.yahoo.com/group/ocaml_beginners>
> Bug reports: http://caml.inria.fr/bin/caml-**bugs<http://caml.inria.fr/bin/caml-bugs>
>
>

[-- Attachment #2: Type: text/html, Size: 4255 bytes --]

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

* Re: [Caml-list] Initialization of a polymorphic field in a record
  2012-07-03 12:25 ` Philippe Veber
@ 2012-07-03 12:33   ` Jonathan Protzenko
  2012-07-03 12:42     ` Gabriel Scherer
  0 siblings, 1 reply; 4+ messages in thread
From: Jonathan Protzenko @ 2012-07-03 12:33 UTC (permalink / raw)
  To: Philippe Veber; +Cc: caml-list, jean-louis.giavitto

The type you would like to assign to make1 is:

make1: (∀x. x → bool) → t

However, as far I understand, the type-system of OCaml introduces the ∀ 
quantifier in front of the function, namely:

make1: ∀x. (x → bool) → t

This means by the time you enter your make1 function, the f function 
has already lost its polymorphic type, since x has been "opened" 
already.

I tried to eta-convert, but that doesn't work either:

let make2 f = let g: 'b. 'b -> bool = fun (type t) (x: t) -> f x in { 
check = g };;
Error: This expression has type t but an expression was expected of 
type t
       The type constructor t would escape its scope

although I *did* think that would be legal.

The only way I know of achieving that is by making make1 take a 
parameter of type t, that is, leave it up to the caller to wrap the 
function in a record with type t so as to keep the polymorphic nature 
of the function...

I really did think there was a way of doing that with the newer (type 
t) features, so I'm hoping for someone to correct my example above :).

Cheers,

jonathan

On Tue 03 Jul 2012 02:25:36 PM CEST, Philippe Veber wrote:
> Hi,
>
> how about that:
>
> # type t = { check : 'a. 'a -> bool };;
> type t = { check : 'a. 'a -> bool; }
>
> # let return_true : 'a. 'a -> bool = fun _ -> true;;
> val return_true : 'a -> bool = <fun>
>
> # let make1 () = { check = return_true; };;
> val make1 : unit -> t = <fun>
>
> cheers,
>   Philippe.
>
>
> 2012/7/3 Jean-Louis Giavitto <jean-louis.giavitto@ircam.fr
> <mailto:jean-louis.giavitto@ircam.fr>>
>
>     Hello.
>
>     I am trying to build a record with a polymorphic field and I am
>     unable to initialize this field. The problem can be summarized as
>     follow. The following definitions works well:
>
>        type t = { check : 'a. 'a -> bool }
>
>        let return_true _ = true
>
>        let make1 () = { check = return_true; }
>
>     But this definition raises an error:
>
>        let make2 f = { check = f; }
>
>     with the message:
>
>       Error: This field value has type 'a -> bool which is less
>     general than
>              'b. 'b -> bool
>
>     Note that
>
>        let return_false _ = true
>
>        let make3 c = { check = if c then return_false else return_true; }
>
>     is working but that
>
>        let g c = if c then return_false else return_true
>        let make4 c = { check = g c; }
>
>     raises the same error message. Making explicit the argument of
>     make does not helps:
>
>       let make5 f = { check = f; }
>       in make5 return_true
>
>     (same error message). And making explicit the type of make does
>     not help neither:
>
>       let make6 : 'a. ('a -> bool) -> t
>       = function f -> { check = f; }
>
>     (same error message).
>
>
>
>     Do you have an idea how I can specify a function similar to make
>     to buid a record of type t?
>
>     In the real life, the argument f will be the result of a
>     computation and instead of a simple signature 'a -> bool, I must
>     deal with a signature
>
>        'a 'b. (('b) #SomeClass as 'a) * 'b -> bool
>
>
>     Thanks for your advice,
>     Jean-Louis Giavitto.
>
>     --
>     Caml-list mailing list.  Subscription management and archives:
>     https://sympa-roc.inria.fr/__wws/info/caml-list
>     <https://sympa-roc.inria.fr/wws/info/caml-list>
>     Beginner's list: http://groups.yahoo.com/group/__ocaml_beginners
>     <http://groups.yahoo.com/group/ocaml_beginners>
>     Bug reports: http://caml.inria.fr/bin/caml-__bugs
>     <http://caml.inria.fr/bin/caml-bugs>
>
>

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

* Re: [Caml-list] Initialization of a polymorphic field in a record
  2012-07-03 12:33   ` Jonathan Protzenko
@ 2012-07-03 12:42     ` Gabriel Scherer
  0 siblings, 0 replies; 4+ messages in thread
From: Gabriel Scherer @ 2012-07-03 12:42 UTC (permalink / raw)
  To: Jonathan Protzenko; +Cc: Philippe Veber, caml-list, jean-louis.giavitto

> I really did think there was a way of doing that with the newer (type t)
> features, so I'm hoping for someone to correct my example above :).

I don't think there is. Indeed, as you remarked, the type required for
`make1` to work would use higher-order polymorphism (a quantification
inside the left type of an arrow), which does not exist in the
Hindley-Milner (HM) type system (because it couldn't be completely
inferred), and is not supported by OCaml in the general case. The only
place where polymorphism can happen is on the function type as a whole
(usual HM prenex polymorphism), or in record fields and object methods
-- but then there is no inference.

So as you suggest, `make1` have to take a structure that already has
this first-class polymorphism baked in : a record or an object (which
has the advantage of needing no type declaration), or possibly a
first-class module (I did not check).

  let make1 (f : < poly : 'a . 'a -> bool >) = { check = fun x -> f#poly x }

On Tue, Jul 3, 2012 at 2:33 PM, Jonathan Protzenko
<jonathan.protzenko@gmail.com> wrote:
> The type you would like to assign to make1 is:
>
> make1: (∀x. x → bool) → t
>
> However, as far I understand, the type-system of OCaml introduces the ∀
> quantifier in front of the function, namely:
>
> make1: ∀x. (x → bool) → t
>
> This means by the time you enter your make1 function, the f function has
> already lost its polymorphic type, since x has been "opened" already.
>
> I tried to eta-convert, but that doesn't work either:
>
> let make2 f = let g: 'b. 'b -> bool = fun (type t) (x: t) -> f x in { check
> = g };;
> Error: This expression has type t but an expression was expected of type t
>       The type constructor t would escape its scope
>
> although I *did* think that would be legal.
>
> The only way I know of achieving that is by making make1 take a parameter of
> type t, that is, leave it up to the caller to wrap the function in a record
> with type t so as to keep the polymorphic nature of the function...
>
> I really did think there was a way of doing that with the newer (type t)
> features, so I'm hoping for someone to correct my example above :).
>
> Cheers,
>
> jonathan
>
>
> On Tue 03 Jul 2012 02:25:36 PM CEST, Philippe Veber wrote:
>>
>> Hi,
>>
>> how about that:
>>
>> # type t = { check : 'a. 'a -> bool };;
>> type t = { check : 'a. 'a -> bool; }
>>
>> # let return_true : 'a. 'a -> bool = fun _ -> true;;
>> val return_true : 'a -> bool = <fun>
>>
>> # let make1 () = { check = return_true; };;
>> val make1 : unit -> t = <fun>
>>
>> cheers,
>>   Philippe.
>>
>>
>> 2012/7/3 Jean-Louis Giavitto <jean-louis.giavitto@ircam.fr
>> <mailto:jean-louis.giavitto@ircam.fr>>
>>
>>
>>     Hello.
>>
>>     I am trying to build a record with a polymorphic field and I am
>>     unable to initialize this field. The problem can be summarized as
>>     follow. The following definitions works well:
>>
>>        type t = { check : 'a. 'a -> bool }
>>
>>        let return_true _ = true
>>
>>        let make1 () = { check = return_true; }
>>
>>     But this definition raises an error:
>>
>>        let make2 f = { check = f; }
>>
>>     with the message:
>>
>>       Error: This field value has type 'a -> bool which is less
>>     general than
>>              'b. 'b -> bool
>>
>>     Note that
>>
>>        let return_false _ = true
>>
>>        let make3 c = { check = if c then return_false else return_true; }
>>
>>     is working but that
>>
>>        let g c = if c then return_false else return_true
>>        let make4 c = { check = g c; }
>>
>>     raises the same error message. Making explicit the argument of
>>     make does not helps:
>>
>>       let make5 f = { check = f; }
>>       in make5 return_true
>>
>>     (same error message). And making explicit the type of make does
>>     not help neither:
>>
>>       let make6 : 'a. ('a -> bool) -> t
>>       = function f -> { check = f; }
>>
>>     (same error message).
>>
>>
>>
>>     Do you have an idea how I can specify a function similar to make
>>     to buid a record of type t?
>>
>>     In the real life, the argument f will be the result of a
>>     computation and instead of a simple signature 'a -> bool, I must
>>     deal with a signature
>>
>>        'a 'b. (('b) #SomeClass as 'a) * 'b -> bool
>>
>>
>>     Thanks for your advice,
>>     Jean-Louis Giavitto.
>>
>>     --
>>     Caml-list mailing list.  Subscription management and archives:
>>     https://sympa-roc.inria.fr/__wws/info/caml-list
>>     <https://sympa-roc.inria.fr/wws/info/caml-list>
>>     Beginner's list: http://groups.yahoo.com/group/__ocaml_beginners
>>     <http://groups.yahoo.com/group/ocaml_beginners>
>>     Bug reports: http://caml.inria.fr/bin/caml-__bugs
>>     <http://caml.inria.fr/bin/caml-bugs>
>>
>>
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/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] 4+ messages in thread

end of thread, other threads:[~2012-07-03 12:43 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-03 12:18 [Caml-list] Initialization of a polymorphic field in a record Jean-Louis Giavitto
2012-07-03 12:25 ` Philippe Veber
2012-07-03 12:33   ` Jonathan Protzenko
2012-07-03 12:42     ` 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).