caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: oleg@okmij.org
To: avatar@hot.ee, jonathan.protzenko@gmail.com
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] typechecking
Date: 23 Mar 2014 04:41:33 -0000	[thread overview]
Message-ID: <20140323044133.99286.qmail@www1.g3.pair.com> (raw)
In-Reply-To: <532DEC4E.6040505@hot.ee>


Misha Aizatulin wrote:
> type t1 = T1
> type t2 = T2
>
> let f T2 = ()
>
> let input (c : in_channel) : t1 =
>   let t = input_value c in
>   f t;
>   t

The expression input_value c has the type 'a. The variable t is
let-bound, so it receives the generalized, polymorphic type
        forall 'a. 'a
In the expression [f t] this polymorphic type is instantiated to t1.
In [t], the last expression of [input], the polymorphic type is
instantiated to t2. There are no problems.

One may shout: wait a minute! The expression [input_value c]
is not syntactically a value. Therefore, the value restriction should
prevent generalization. The classical value restriction indeed does
prevent. But OCaml has a relaxed value restriction. For example, the
following legitimate code

        let foo () = []
                val foo : unit -> 'a list = <fun>
        let f [1] = ()
                val f : int list -> unit = <fun>
        let bar () : char list =
          let t = foo () in
          f t;
          t
                val bar : unit -> char list = <fun>

typechecks in OCaml -- but it wouldn't under the classical
value restriction. The paper

    Jacques Garrigue: Relaxing the Value Restriction.
    Proc. Int. Symposium on Functional and Logic Programming, Nara, April 2004. 
    LNCS 2998, pp. 196--213. (extended version: RIMS Preprint 1444)
    < http://www.math.nagoya-u.ac.jp/~garrigue/papers/morepoly-long.pdf >

explains very well why the original value restriction is too
restrictive.

So, what to do about the original problem?

Jonathan Protzenko recommended:
> I was also surprised by this example, and I kind of expected
> input_value to have type in_channel -> '_a.
> Since writing '_a is not allowed, I guess there's not much we can do here.

Although writing the type '_a in a type annotation is not allowed,
internally such a type could be ascribed to a value (I side-step murky
separate compilation issues that creates). So, one could have
input_value of the type Jonathan wants. Alas, that is too
restrictive. Consider

        let ll = ref [];;
                val ll : '_a list ref = {contents = []}
        let input_list (c:in_channel) = !ll;;
                val input_list : in_channel -> '_a list = <fun>

        let c = open_in "/dev/null" in
        (1::input_list c, true::input_list c)

        Error: This expression has type int list
        but an expression was expected of type bool list
        Type int is not compatible with type bool 

Some if input_value has the type Jonathan suggest, we can only use
input_value to read the values of the same type.

One solution is to give input_value a sound type such as the
following:

        val input_value : 'a -> in_channel -> 'a

That is, input_value should receive _some_ value of the type it is
supposed to read. The user must provide the evidence that the type to
read is populated. One problem: it is too
cumbersome in practice. The second problem is that function types are
all populated -- by, for example, [fun _ -> failwith "black hole"].

The complete solution is to update the function
        generalize_expansive in typing/ctype.ml
which is responsible for implementing the relaxed value restriction.
The type 'a should not be considered co-variant in 'a. Alas, such a
modification is a bit cumbersome since generalize_expansive is called
recursively. One have to split cases. It is not clear how much benefit
can be gained -- complicating type checker for the sake of a rare
error.



  parent reply	other threads:[~2014-03-23  4:41 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-22 20:02 Misha Aizatulin
2014-03-22 20:40 ` Daniel Bünzli
2014-03-22 22:12   ` Yaron Minsky
2014-03-22 22:24     ` Jonathan Protzenko
2014-03-23  4:41 ` oleg [this message]
2014-03-23 12:59   ` Jacques Garrigue
2014-03-24  8:46     ` Alain Frisch

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=20140323044133.99286.qmail@www1.g3.pair.com \
    --to=oleg@okmij.org \
    --cc=avatar@hot.ee \
    --cc=caml-list@inria.fr \
    --cc=jonathan.protzenko@gmail.com \
    /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).