From: "Daniel Bünzli" <daniel.buenzli@erratique.ch>
To: Philippe Veber <philippe.veber@gmail.com>
Cc: Caml-list <caml-list@inria.fr>,
Pierre Chambart <pierre.chambart@laposte.net>
Subject: Re: [Caml-list] Phantom types and variants
Date: Sat, 23 Aug 2014 16:06:50 +0100 [thread overview]
Message-ID: <B247E15ECDE34E3089ED79B9FF32EAE0@erratique.ch> (raw)
In-Reply-To: <CAOOOohTUcDLfsDRSh7fu7F8xSbPx6CJ4bX0Muz-6mNwc4QHddQ@mail.gmail.com>
Le vendredi, 22 août 2014 à 20:49, Philippe Veber a écrit :
> Here is another proposal:
Thanks Philippe. I also thought about this solution but I wanted to avoid the new allocation. Note that you can actually write that solution without having to write that eq function. This makes the trick:
let coerce kind v = match kind with
| kind when (kind :> kind) = (v.kind :> kind) -> { v with kind = kind }
| _ -> invalid_arg ""
Pierre Chambart also responded to me privately (thanks), suggesting that I do not try to use variants themselves as the coercion specification but another more structured value. His solution (at the end of this email) works. But since I'm a little bit stubborn and that I would really like to use the variant for the coercion specification I tried to adapt its solution as follows. But it fails with a type error that I fail to understand:
Error: This definition has type ([< kind ] as 'a) -> 'a t
which is less general than 'b. ([< kind ] as 'b) -> 'b t
-------------
module M : sig
type kind = [ `A | `B ]
type +'a t constraint 'a = [< kind ]
val a : unit -> [> `A] t
val b : unit -> [> `B] t
val coerce : ([< kind] as 'a) -> 'b t -> 'a t
end = struct
type kind = [ `A | `B ]
type +'a t =
{ kind : kind;
coerce : 'b. ([< kind] as 'b) -> 'b t }
constraint 'a = [< kind ]
let a () =
let rec v = { kind = `A; coerce }
and coerce : 'b. ([< kind] as 'b) -> 'b t = function
| `A -> v | `B -> invalid_arg ""
in
v
let b () =
let rec v = { kind = `B; coerce }
and coerce : 'b. ([< kind] as 'b) ->'b t = function
| `A -> v | `B -> invalid_arg ""
in
v
let coerce kind v = v.coerce kind
end
-----------
Any hints ?
Best,
Daniel
Pierre Chambart's solution:
module M : sig
type kind = [ `A | `B ]
type +'a t constraint 'a = [< kind ]
type 'a coercer constraint 'a = [< kind]
val a : unit -> [> `A] t
val b : unit -> [> `B] t
val ac : [`A] coercer
val coerce : 'a coercer -> 'b t -> 'a t
end = struct
type kind = [ `A | `B ]
type +'a t =
{ kind : kind }
constraint 'a = [< kind]
type 'a coercer =
{ f : 'b. 'b t -> 'a t option }
constraint 'a = [< kind]
let a () = { kind = `A }
let b () = { kind = `B }
let ac = { f = (function ({ kind = `A } as v) -> Some v
| _ -> None) }
let coerce k v =
match k.f v with
| None -> invalid_arg ""
| Some v -> v
end
next prev parent reply other threads:[~2014-08-23 15:07 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-22 3:11 Daniel Bünzli
2014-08-22 3:17 ` Daniel Bünzli
2014-08-22 19:49 ` Philippe Veber
2014-08-23 15:06 ` Daniel Bünzli [this message]
2014-08-23 15:40 ` Jeremy Yallop
2014-08-23 15:48 ` Daniel Bünzli
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=B247E15ECDE34E3089ED79B9FF32EAE0@erratique.ch \
--to=daniel.buenzli@erratique.ch \
--cc=caml-list@inria.fr \
--cc=philippe.veber@gmail.com \
--cc=pierre.chambart@laposte.net \
/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).