From: Leo White <lpw25@cam.ac.uk>
To: Arnaud Spiwack <arnaud@spiwack.net>
Cc: OCaML Mailing List <caml-list@inria.fr>
Subject: Re: [Caml-list] Manipulating Modules Modularly
Date: Tue, 21 Oct 2014 13:26:13 +0100 [thread overview]
Message-ID: <8638ahpq1m.fsf@cam.ac.uk> (raw)
In-Reply-To: <CAMoPVjczx6CWEOZ9W+PenQehmhgMPB_K1zTd6nyQPL5RV0Yoiw@mail.gmail.com> (Arnaud Spiwack's message of "Tue, 21 Oct 2014 10:52:02 +0200")
> module type M = sig type t val u:t val p:t->t->t end
>
> And a functor:
>
> module type ME = sig type t val ps:t list -> t end
> module ME (M:M) : ME with type t := M.t
>
> All good and well. I now want to reuse my functor for list, which are a monoid.
> What I really want is a module
>
> module LE : ME with type t := 'a list
>
> So here's my question: how do you/would you solve this problem. If the solution is compatible with 3.12, it's a plus.
>
Moving quantifiers around is awkward in the module system, but is also
not safe in general. We can clearly illustrate this by reencoding your
example without modules:
First we define `m` as a record type and create one for lists:
# type 'a m = { u : 'a; p : 'a -> 'a -> 'a };;
type 'a m = { u : 'a; p : 'a -> 'a -> 'a; }
# let list = { u = []; p = (@) };;
val list : 'a list m = {u = []; p = <fun>}
Then we define the `me` as another record type and create a simple
function for creating them from monoids:
# type 'a me = { ps : 'a list -> 'a };;
type 'a me = { ps : 'a list -> 'a; }
# let me (m : 'a m) = { ps = List.fold_left m.p m.u };;
val me : 'a m -> 'a me = <fun>
Now we can apply the `me` function to the `list` monoid:
# let mel = me list;;
val mel : '_a list me = {ps = <fun>}
But what we get is only weakly polymophic because of the value
restriction. This hints at the unsafety of what we are trying to
do. Whilst the above definition of `me` happens to be safe, consider the
following version:
# let me (m : 'a m) =
let r = ref m.u in
let ps = function
| [] -> !r
| x :: xs ->
let old = !r in
r := x;
List.fold_left m.p m.u (old :: xs)
in
{ps};;
val me : 'a m -> 'a me = <fun>
# let mel = me list;;
val mel : '_a list me = {ps = <fun>}
Here we use a reference to preserve elements of the monoid across
different calls to `ps`. If this were allowed to be polymorphic we could
end up mixing elements of different list types together. For example, if
we use `Obj.magic` to pretend that `mel` is polymorphic we can quickly
get a segfault:
# let meli : int list me = Obj.magic mel;;
val meli : int list me = {ps = <fun>}
# let melf : float list me = Obj.magic mel;;
val melf : float list me = {ps = <fun>}
# meli.ps [[1; 2; 3]; [2; 3; 4]];;
- : int list = [2; 3; 4]
# melf.ps [[1.0; 2.0; 3.0]; [2.0; 3.0; 4.0]];;
Process ocaml-toplevel segmentation fault
So hopefully, this illustrates why you cannot easily get what you want
in a language with side-effects. Since what you are fundementally trying
to do is safe, I suspect that a language with good support for
higher-rank polymorphism, higher-kinded polymorphism, and kind
polymorphism might be apply to encode it safely even in the presence of
side-effects, but the encoding is likely to be a bit involved.
Regards,
Leo
next prev parent reply other threads:[~2014-10-21 12:26 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-10-21 8:52 Arnaud Spiwack
2014-10-21 12:26 ` Leo White [this message]
2014-10-21 12:47 ` Leo White
2014-10-21 13:19 ` Arnaud Spiwack
2014-10-21 14:52 ` Leo White
2014-10-22 9:51 ` Arnaud Spiwack
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=8638ahpq1m.fsf@cam.ac.uk \
--to=lpw25@cam.ac.uk \
--cc=arnaud@spiwack.net \
--cc=caml-list@inria.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