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
next prev parent 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