caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Jacques Le Normand <rathereasy@gmail.com>
To: Jacques Garrigue <garrigue@math.nagoya-u.ac.jp>
Cc: OCaML List Mailing <caml-list@inria.fr>
Subject: Re: [Caml-list] Request for feedback: A problem with injectivity and GADTs
Date: Sun, 28 Apr 2013 22:17:01 -0700	[thread overview]
Message-ID: <CAK0y-36uPAAXGanrhZKQOQAPsELjTFxM1Av820da-mU4kqTVfg@mail.gmail.com> (raw)
In-Reply-To: <00C57DF0-C6F0-4EDE-8607-2155F3A17146@math.nagoya-u.ac.jp>

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

Fully injective types are the norm. It would have been nice to have a "non
injectivity" or "phantom type" annotation. Since phantom types are seldom
used, beginners won't get confused. It might even help beginners understand
the concept of a phantom type.



On Sat, Apr 27, 2013 at 5:02 PM, Jacques Garrigue <
garrigue@math.nagoya-u.ac.jp> wrote:

> Some of you may already be aware of PR#5985
> http://caml.inria.fr/mantis/view.php?id=5985
>
> To explain very shortly what is happening, a bug was found in the ocaml
> compiler, both 4.00 and the development version, such that one that
> convert a value from any type to any other type, bypassing all checks.
> This is what we call a soundness bug, a hole in the type system.
>
> Such problems happen at times, and we are usually very fast to fix them.
> However this time the problem is bit more subtle, because fixing it
> straightforwardly may make impossible to write a whole category of
> GADTs. Hence this request for feedback.
>
> Practical description of the problem:
>
> It is quite usual to write type witnesses using a GADT:
>
> type _ ty =
>   | Int : int ty
>   | Pair : 'a ty * 'b ty -> ('a * 'b) ty
>   | Hashtbl : 'a ty * 'b ty -> ('a, 'b) Hashtbl.t ty
>
> This looks fine, but now suppose that we write the following code:
>
> module F (X : sig type 'a t end) = struct
>    type _ ty =
>     | Int : int ty
>     | Pair : 'a ty * 'b ty -> ('a * 'b) ty
>     | T : 'a ty -> 'a X.t ty
> end
>
> The idea is to create a type witness with the
> type constructor X.t instead of Hashtbl.t.
> Now I can use it this way:
>
> module U = struct type 'a t = unit end
> module M = F(U)
> let w = M.T M.Int
> (* val w : int U.t M.ty *)
> let w' = match w with M.T x -> x | _ -> assert false
> (* val w' : '_a M.ty = M.Int *)
>
> What this means is that we can now give an arbitrary type
> to a witness for int. You can easily use it to build a function
> from int to any  type:
>
> let f : type a. a M.ty -> int -> a =
>   fun w x -> match w with M.Int -> x | _ -> assert false;;
> let g : int -> float = f w';;
>
> If we look at the source of the problem, it lies in the fact U.t is not
> injective.
> I.e. when we define a GADT, we assume that all the type variables in
> the return type can be determined from the type parameter.
> That is, from (int U.t M.ty) we assume that the type of the argument of T
> is (int M.ty).
> However, since U.t is not injective, int U.t is actually equal to any type
> 'a U.t,
> and we can convert.
> Note that, for known types, injectivity was already checked.
> I.e., the following definition is not accepted:
>
> type _ ty =
>   | Int : int ty
>   | Pair : 'a ty * 'b ty -> ('a * 'b) ty
>   | T : 'a ty -> 'a U.t ty
>
> However, abstract types were assumed to be injective.
> Here we see that you cannot take this for granted.
>
> The problem is of course not limited to type witnesses, and not even GADTs:
> types with constrained parameters (introduced at the very beginning of
> ocaml),
> can also trigger it.
> And you don't need a functor to trigger it: once you know that two types
> are equal
> in some scope, there are many ways to leak that information.
>
> =============================
> Here comes the request for feedback:
>
> The fix is simple enough: we should track injectivity, and assume that
> abstract
> types are not injective by default.
> However, this also means that the first type I defined above (using
> Hashtbl.t)
> will be refused.
>
> How many of you are using GADTs in this way, and how dependent are you on
> abstract types ?
>
>
> If we need to be able to define GADTs relying on the injectivity of some
> abstract
> types, a straightforward solution is to add injectivity annotations on
> type parameters,
> the same way it was done for variance:
>
>   type #'a t
>
> would mean that t is injective.
> This is implemented in branches/non-vanishing, in the subversion
> repository.
>         svn checkout http://caml.inria.fr/svn/branches/non-vanishing
> Note that in that branch Hashtbl.t in the standard library is marked as
> injective.
> This introduces some new syntax, and libraries have to be modified to
> benefit,
> so the question is do we really need it?
>
>
> Jacques Garrigue
>
> P.S.
> If you are curious about other difficulties of GADTs, the is also
> branches/abstract-new
> which introduces a notion of new types, either concrete or abstract, which
> are guaranteed
> to be distinct from each other, and any other concrete type. This is
> useful when
> checking the exhaustiveness of pattern-matching, as we can then discard
> impossible
> branches. That branch is completely experimental.
>
>
> --
> 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

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

  parent reply	other threads:[~2013-04-29  5:17 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-04-28  0:02 Jacques Garrigue
2013-04-28  2:45 ` Markus Mottl
2013-04-28 10:28   ` Jacques Garrigue
2013-04-28  5:54 ` Jacques Le Normand
2013-04-29  3:45 ` Ivan Gotovchits
2013-04-29  4:03   ` Ivan Gotovchits
2013-04-29  5:17 ` Jacques Le Normand [this message]
2013-04-29  7:58   ` Alain Frisch
2013-04-29 10:52     ` Jacques Garrigue
2013-04-29 11:23       ` Alain Frisch
2013-04-29 16:37         ` Nathan Mishra Linger
2013-04-29 23:53           ` Jacques Garrigue
2013-04-30  5:45       ` Jacques Garrigue
2013-05-04  6:46         ` Jacques Garrigue
2013-05-04  7:09           ` Gabriel Scherer
2013-05-04 12:28             ` Jacques Garrigue
2013-04-30  6:59       ` Alain Frisch
2013-04-30  7:56         ` Jacques Garrigue
2013-04-30  8:02           ` Alain Frisch
2013-04-30  8:18             ` Jacques Garrigue
2013-04-30  9:11               ` Gabriel Scherer
2013-04-30  9:55                 ` Jacques Garrigue
2013-04-30 10:12                   ` Leo White
2013-04-30 11:30                     ` Gabriel Scherer
2013-04-30 13:06                       ` Leo White
2013-04-29  7:59   ` Gabriel Scherer
2013-07-01 14:47 ` Alain Frisch
2013-07-01 23:20   ` Jacques Garrigue
2013-07-03 16:08     ` Alain Frisch
2013-07-03 16:13       ` Gabriel Scherer
2013-07-04  6:07         ` [Caml-list] Request for feedback: A problem with injectivity oleg
2013-07-04  7:35           ` Alain Frisch
2013-07-05 10:30             ` oleg
2013-07-05 12:02               ` Alain Frisch
2013-07-04  1:00       ` [Caml-list] Request for feedback: A problem with injectivity and GADTs Jacques Garrigue
2013-07-04  8:14         ` Alain Frisch
2013-07-04  8:52           ` Jacques Garrigue

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=CAK0y-36uPAAXGanrhZKQOQAPsELjTFxM1Av820da-mU4kqTVfg@mail.gmail.com \
    --to=rathereasy@gmail.com \
    --cc=caml-list@inria.fr \
    --cc=garrigue@math.nagoya-u.ac.jp \
    /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;
as well as URLs for NNTP newsgroup(s).