From: Mikhail Mandrykin <mandrykin@ispras.ru>
To: caml-list@inria.fr
Cc: Markus Mottl <markus.mottl@gmail.com>
Subject: Re: [Caml-list] Covariant GADTs
Date: Mon, 19 Sep 2016 13:18:19 +0300 [thread overview]
Message-ID: <2161155.JggR3X9ZFM@molnar> (raw)
In-Reply-To: <a4859b23-5300-4205-3cac-3f19888c30dd@polychoron.fr>
[-- Attachment #1: Type: text/plain, Size: 2247 bytes --]
Hello,
On понедельник, 19 сентября 2016 г. 10:58:29 MSK you wrote:
> Hi Markus,
>
> Therefore, these fields are neither readable nor writable directly. A
> direct manifestation of the problem is that, as you observed, you cannot
> assign new values to either prev or next without use of `Obj.magic`. For
> instance,
As far as I know quite common approach in this case is introduction of one-
constructor wrapper types to hide the existential variable and allow mutability
e.g.
type ('el, _) t =
| Empty : ('el, [ `empty ]) t
| Elt : {
mutable prev : 'el link;
el : 'el;
mutable next : 'el link;
} -> ('el, [ `elt ]) t
and 'el link = Link : ('el, _) t -> 'el link;;
So the link type wraps the type parameter of the next element and thus allows
safe mutation, otherwise it's only possible to update the field with the element of
exactly same type that doesn't allow e.g. deleting an element at the end of the list
without reallocating the corresponding record of the previous element (and if one
decides to keep more precise information e.g. about the number of elements, the
whole list needs to be re-allocated). With the link wrapper as above it's possible to
define add, remove and also a get operation without and extra pattern matching:
let add : type a. _ -> (_, a) t -> (_, [`elt]) t = fun el ->
function
| Empty -> Elt { el; prev = Link Empty; next = Link Empty }
| Elt _ as n -> Elt { el; prev = Link Empty; next = Link n };;
let remove : type a. ('el, a) t -> 'el link =
function
| Empty -> Link Empty
| Elt { prev = Link p as prev; next = Link n as next} ->
(match p with Empty -> () | Elt p -> p.next <- next);
(match n with Empty -> () | Elt n -> n.prev <- prev);
next;;
let get : (_, [`elt]) t -> _ = function Elt { el; _ } -> el
Also note the GPR#606(https://github.com/ocaml/ocaml/pull/606[1] ) that should
allow constructing and deconstructing links (Link l) without overhead.
Regards, Mikhail
--
Mikhail Mandrykin
Linux Verification Center, ISPRAS
web: http://linuxtesting.org
e-mail: mandrykin@ispras.ru
--------
[1] https://github.com/ocaml/ocaml/pull/606
[-- Attachment #2: Type: text/html, Size: 9761 bytes --]
next prev parent reply other threads:[~2016-09-19 10:18 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-09-17 17:38 Markus Mottl
2016-09-18 8:17 ` Petter A. Urkedal
2016-09-19 1:52 ` Markus Mottl
2016-09-19 8:58 ` octachron
2016-09-19 10:18 ` Mikhail Mandrykin [this message]
2016-09-19 13:37 ` Mikhail Mandrykin
2016-09-19 14:46 ` Markus Mottl
2016-09-19 14:53 ` Mikhail Mandrykin
2016-09-19 15:03 ` Markus Mottl
2016-09-20 21:07 ` Markus Mottl
2016-09-21 10:11 ` Lukasz Stafiniak
2016-09-21 10:14 ` Lukasz Stafiniak
2016-09-21 17:04 ` Markus Mottl
2016-09-21 21:40 ` Gabriel Scherer
2016-09-22 0:39 ` Markus Mottl
2016-09-24 5:09 ` Yaron Minsky
2016-10-04 10:33 ` Jacques Garrigue
2016-09-19 14:39 ` Markus Mottl
2016-09-19 10:05 ` Goswin von Brederlow
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=2161155.JggR3X9ZFM@molnar \
--to=mandrykin@ispras.ru \
--cc=caml-list@inria.fr \
--cc=markus.mottl@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