Mailing list for all users of the OCaml language and system.
 help / color / mirror / Atom feed
From: Gabriel Scherer <gabriel.scherer@gmail.com>
To: Ivan Gotovchits <ivg@ieee.org>
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] GADT and locally ADT
Date: Tue, 4 Jun 2013 11:23:01 +0200	[thread overview]
Message-ID: <CAPFanBE=Zs_tzNqaJ_2YMjoeH+ycc=O6SF2MAbW6y-kMbgB5aA@mail.gmail.com> (raw)
In-Reply-To: <87a9n6s5jo.fsf@golf.niidar.ru>

In expressions, type variables 'a 'b do not enforce polymorphism, they
are merely name for types that will be inferred.
  let f : 'a -> 'a = fun x -> x + 1
is accepted. So your second example with ('a, 'b) does not enforce polymorphism.

This is not in general a problem as if the inferred type is indeed a
type variable, it will be generalized by the inference algorithm and
therefore "turned into polymorphism" after type inference. It is
problematic however for polymorphic recursive functions (this form of
polymorphism would have to be "guessed" before the recursive
definition is type-checked, and therefore requires an annotation), and
for GADTs.

There are two *distinct* notions used to enforce polymorphism:
- polymorphic type variables as in
    val f : 'a -> 'a
  or
    let f : 'a . 'a -> 'a = ...
  (useful for polymorphic recursion)
- local abstract types
   let f (type t) : t -> t = ...
   fun (type t) -> ...
  (useful for GADTs)

Local abstract types are documented in
http://caml.inria.fr/pub/docs/manual-ocaml/manual021.html#toc80 . They
are not type variable (they cannot be unified with anything, hence
enforce polymorphism), but type "constructors" syntactically (like
'list' in ('a list), but without a parameter). We say that GADTs
introduce equations and refine types; they can only refine local
abstract types, not type variables. The refinement of GADT types is
similar to what happen when you traverse a module abstraction, outside
you know the abstract type M.t, and inside you know (type M.t = int).

Due to this "implementation detail" of GADTs, the following code (that
enforces polymorphism) would still fail to type-check:

    let f : 'b . ('a, 'b) access -> unit = function
      | ReadWrite ch -> ()
      | Read ch -> ()

while the following work

    let f (type t) : ('a, t) access -> unit = function
      | ReadWrite ch -> ()
      | Read ch -> ()

Finally, the syntax

   let f : type t . ('a, t) acc -> unit = function ...

is a merge of both ('a 'b . ...) and ((type t) ...): it provides a
local type constructor, and enables polymorphic recursion. This is
what you should use when you write recursive functions using GADTs.




On Tue, Jun 4, 2013 at 9:23 AM, Ivan Gotovchits <ivg@ieee.org> wrote:
> Gabriel Scherer <gabriel.scherer@gmail.com> writes:
>
>> If the function knows (or infer) that the argument type is (ro), then
>> there is only one case to handle. But there is also a function that is
>> polymorphic over the second argument, and it must be callable with
>> both (ro) and (rw) values : this function works "for any access mode".
>> This is what the annotated function
>>
>>>      let f (type t)  (inp: ('a,t) access)  = match inp with
>>>        | ReadWrite (ch) -> ()
>>>        | Read (ch) -> ();;
>>
>> does.
>
> Looks reasonable, but can you, please, explain the difference between
> function:
>
>     let f (type t)  (inp: ('a,t) access)  = match inp with
>       | ReadWrite ch -> ()
>       | Read ch -> ()
>
> that have type
>
>     val f : ('a, 'b) access -> unit
>
> and
>
>     let f (inp: ('a,'b) access)  = match inp with
>       | ReadWrite ch -> ()
>       | Read ch -> ()
>
> that fails to type check:
>
> Error: This pattern matches values of type ('a, ro) access
>        but a pattern was expected which matches values of type
>          ('a, rw) access

  reply	other threads:[~2013-06-04  9:23 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-06-04  4:06 Ivan Gotovchits
2013-06-04  5:47 ` Gabriel Scherer
2013-06-04  7:23   ` Ivan Gotovchits
2013-06-04  9:23     ` Gabriel Scherer [this message]
2013-06-04 11:50       ` Ivan Gotovchits

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAPFanBE=Zs_tzNqaJ_2YMjoeH+ycc=O6SF2MAbW6y-kMbgB5aA@mail.gmail.com' \
    --to=gabriel.scherer@gmail.com \
    --cc=caml-list@inria.fr \
    --cc=ivg@ieee.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox