From: Jacques Garrigue <garrigue@math.nagoya-u.ac.jp>
To: Gabriel Scherer <gabriel.scherer@gmail.com>
Cc: Rodolphe Lepigre <rodolphe.lepigre@univ-savoie.fr>,
Mailing List OCaml <caml-list@inria.fr>
Subject: Re: [Caml-list] GADT magic
Date: Mon, 5 Oct 2015 10:27:16 +0900 [thread overview]
Message-ID: <44040573-4A4A-40DB-9E67-A4E04054606E@math.nagoya-u.ac.jp> (raw)
In-Reply-To: <CAPFanBGDmM3-KQ9iPPMA4KhBxnXLWkg6mCzM24tzVA7L4MGqFw@mail.gmail.com>
On 2015/10/03 17:54, Gabriel Scherer wrote:
>
> This is normal behavior. You rely on the fact, when you write "| t ->
> t", that the remaining case is App which returns a (t term). But the
> type-checker will only learn this fact by opening the App constructor,
> which you do in the "fully explicit" version.
>
> (The type-checker is already "opening constructors" and exploring
> cases by itself as part of the exhaustiveness/redundancy pattern
> checking that Jacques Garrigue discussed at the OCaml Workshop 2015.
> Jacques, is there any improvement that is possible in this case
> without too much bakctracking?)
Actually, I would have very little hope for the second version of
expr_to_term
let expr_to_term : type a. a expr -> term = function
| LVar(x) -> LVar(x)
| LAbs(f) -> LAbs(f)
| t -> t
The type checking algorithm never tries to infer the possible
values behind a variable pattern, taking into account the other
cases of the pattern-matching. The exhaustiveness check does
it, but it runs after type-checking.
On the other hand, one could consider handling or-patterns:
let expr_to_term : type a. a expr -> term = function
LVar _ | LAbs _ | Appl _ as t -> t
The idea would be to typecheck each case separately, as somebody
already suggested. Since the result is to turn expr_to_term into
immediate identity, this may be worth considering.
My only concern is that it may not play well with type based optimizations.
Jacques Garrigue
> On Sat, Oct 3, 2015 at 9:02 AM, Rodolphe Lepigre
> <rodolphe.lepigre@univ-savoie.fr> wrote:
>> Dear list,
>>
>> I am using a GADT and some phantom types to implement an abstract syntax
>> tree for some functional programming language, say the λ-calculus.
>>
>> My first type definition was something like:
>>
>> ==========
>> type valu =
>> | LVar of string
>> | LAbs of valu -> term
>> and term =
>> | Valu of valu
>> | Appl of term * term
>> ==========
>>
>> This works fine, but it is annoying to work with because of the coercion
>> constructor "Valu". Then I decided to be to smarter and use some GADT and
>> phantom types:
>>
>> ==========
>> type v
>> type t
>>
>> type _ expr =
>> | LVar : string -> 'a expr
>> | LAbs : (v expr -> 'b expr) -> 'a expr
>> | Appl : 'a expr * 'b expr -> t expr
>>
>> type term = t expr
>> type valu = v expr
>> ==========
>>
>> This definition is much more convenient since the type "valu" is (kind of)
>> a subtype of the type "term". It is not a real subtype since I had to
>> define a function with the type:
>>
>> ==========
>> val expr_to_term : type a. a expr -> term
>> ==========
>>
>> This function is exactly the identity function, but for the type checker
>> to accept it I need to be quite explicit:
>>
>> ==========
>> let expr_to_term : type a. a expr -> term = function
>> | LVar(x) -> LVar(x)
>> | LAbs(f) -> LAbs(f)
>> | Appl(t,u) -> Appl(t,u)
>> ==========
>>
>> Of course, a better and more efficient implementation for this function
>> is "Obj.magic", but this is not the question here. I was expecting the
>> following definition to work:
>>
>> ==========
>> let expr_to_term : type a. a expr -> term = function
>> | LVar(x) -> LVar(x)
>> | LAbs(f) -> LAbs(f)
>> | t -> t
>> ==========
>>
>> But it does not type check. This is weird because all remaining patterns
>> captured by the "t" have type "term"...
>>
>> Is this normal behaviour? Is this a bug?
>>
>> Rodolphe
>> --
>> Rodolphe Lepigre
>> LAMA, Université Savoie Mont Blanc, FRANCE
>> http://lama.univ-smb.fr/~lepigre/
>>
>> --
>> 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
prev parent reply other threads:[~2015-10-05 1:27 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-10-03 7:02 Rodolphe Lepigre
2015-10-03 8:54 ` Gabriel Scherer
2015-10-05 1:27 ` Jacques Garrigue [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=44040573-4A4A-40DB-9E67-A4E04054606E@math.nagoya-u.ac.jp \
--to=garrigue@math.nagoya-u.ac.jp \
--cc=caml-list@inria.fr \
--cc=gabriel.scherer@gmail.com \
--cc=rodolphe.lepigre@univ-savoie.fr \
/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