caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Michael Alexander Hamburg <hamburg@fas.harvard.edu>
To: Damien Bobillot <damien.bobillot@m4x.org>
Cc: caml-list@inria.fr
Subject: Re: [Caml-list] signature and 'a generic types
Date: Mon, 20 Jun 2005 18:31:11 -0400	[thread overview]
Message-ID: <1119306671.42b743af64539@webmail.fas.harvard.edu> (raw)
In-Reply-To: <C6B8033B-6F2E-490D-85BB-55B37407448E@m4x.org>

Quoting Damien Bobillot <damien.bobillot@m4x.org>:

> Hello,
>
> Look at the following code :
>
>      module Module : (sig val func : 'a -> 'b end) =
>      struct let func a = a end
>
> Here Module.func's type is 'a -> 'a. According to me 'a -> 'a is a
> subtype of 'a -> 'b, it's 'a -> 'b with 'a = 'b. Nevertheless ocamlc
> give the following error :
>
>      Values do not match:
>        val func : 'a -> 'a
>      is not included in
>        val func : 'a -> 'b
>
> Why ?
>

The module signature requires that the function have type 'a -> 'b for all 'a
and 'b, i.e. the declared type must be a subtype of the actual type, not vice
versa.  Imagine if the compiler let you use that module definition, someone
calling the module would be able to say "hello" ^ Module.func 1, and OCaml
would try to treat 1 as a string because func is declared to have type 'a ->
'b.

> I also try to use the reverse match :
>
>      module Module : (sig val func : 'a -> 'a end) = struct
>          let l = ref []
>          let func a = List.assoc a !l
>      end
>
> Where Module.func is of type 'a -> 'b. Ocamlc also give me an error,
> but I completely understand it here : 'a -> 'b is really not a
> subtype of 'a -> 'a.

Ah, but the function you declared is not of type 'a -> 'b but rather of type '_a
-> '_b, because ref [] does not refer to _every_type_ ('a ref), but rather
_one_single_type_ ('_a ref).  This is the infamous "value polymorphism
restriction".  Here's why it's there:

let l = ref [] (* type of l is '_a list ref, not 'a list ref *)
let () = l := ["hello"] (* if there were no VPR, l would still have type 'a list
ref here, but because it has one single type, it is now a string list ref *)
let x = 1+List.head !l (* if there were no VPR, this would be allowed, and try
to compute 1+"hello" *)
let () = l := [7] (* this is also disallowed by the type of l.  You can't get it
back to being an '_a list ref *)

In any case, 'a -> 'a is not a subtype of '_a -> '_b.  If your func had been
Obj.magic, or a -> List.assoc a [], or a -> failwith "Hello world", it would
have worked (I think, I don't have OCaml in front of me).

> In this case I also don't understand why neither " 'a -> 'b is
> included in 'a -> 'a " nor " 'a -> 'a is included in 'a -> 'b " are
> true. To my mind, one should be true.
>
> Is it a caml limitation/bug, or am I wrong somewhere ?

Sort of.  First, the VPR is somewhat more restrictive than it has to be for type
safety, but analyzing exactly how restrictive is has to be in a particular case
is hard (very hard in this case; it's hard for the compiler to know that a
particular piece of mutable state will never be mutated anywhere), and would
require extra notation to avoid breaking across module boundaries.  The current
restriction is sort of a happy medium.

Second, in OCaml, polymorphic types are abbreviated.  "'a -> 'a" is an
abbreviation of "for all types 'a, 'a -> 'a", whereas "'_a -> '_a" is an
abbrevation of "for one single arbitrary type 'a, 'a -> 'a".  These
abbreviations are somewhat confusing.  They also assume knowledge of a
restriction of so-called Hindley-Milner types, which is that all the "forall"s
go out in front.  This restriction is required for automatic type detection to
be computable, so it can be lifted only if the user specifies the type.  For
some reason, in OCaml the syntax only allows you to do this in record
declarations, which could probably be considered a "limitation/bug".

Mike Hamburg

> --
> Damien Bobillot
>
>





      parent reply	other threads:[~2005-06-20 22:31 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-06-20 15:20 Damien Bobillot
2005-06-20 15:59 ` [Caml-list] " Virgile Prevosto
2005-06-20 16:06 ` Stephane Glondu
2005-06-20 16:19 ` Marcin 'Qrczak' Kowalczyk
2005-06-20 22:31 ` Michael Alexander Hamburg [this message]

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=1119306671.42b743af64539@webmail.fas.harvard.edu \
    --to=hamburg@fas.harvard.edu \
    --cc=caml-list@inria.fr \
    --cc=damien.bobillot@m4x.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;
as well as URLs for NNTP newsgroup(s).