From: Dmitry Grebeniuk <gdsfh1@gmail.com>
To: caml-list@inria.fr
Subject: [Caml-list] recursive module, object types, tying knot
Date: Thu, 8 Sep 2011 00:29:20 +0300 [thread overview]
Message-ID: <CAPi0vKXHQ3SyChtphJ7OAtAnDNK5TpfXqq_nKBF7aA0nGHovHw@mail.gmail.com> (raw)
Hello.
I have an usual question. I want to make some object
types (container-like) that can map the stored contents
with its method. For example, let the container will be
the simple list:
class ['a] (lst : list 'a) = object ...
method map : ('a -> 'b) -> 'b lst
The compiler yields an error:
# class ['a] lst x = object
method map : 'b . ('a -> 'b) -> 'b lst
= fun f -> List.map f x end;;
Error: This type scheme cannot quantify 'b :
it escapes this scope.
I know the solution with separate function for map,
but I don't like it: the whole mess with objects is
to use less information to make api call: compare
"MapIntToString.get my_map 123" with
"my_map#get 123". Having to remember where
(in which module) the correct map function resides
will ruin the purpose of the code I'm writing now.
(maybe "implicit values" could help here, but they are
not the part of official compiler for now.)
I need to write the code that performs that map, maybe
with help of some additional types and values. And I
began experimenting.
Now I have two pieces of code (for even simpler
container, that contains just one value), the second one
is derived from the first one by replacing the type "ta"
from the record to the object type. The first piece
of code works, but the second does not. Why there is
such a difference, and, more importantly, how should
I tweak the second piece of code to make it work?
(if you remember, referencing the record's fields will
require the path to the module where the record
is declared (see the "q#tbm.L.tam" subexpression),
so the first "solution" is not a solution for my current
problem.)
$ ocaml
Objective Caml version 3.12.1+rc1
# module rec L
:
sig
type 'a ta = { tam : 'b. ('a -> 'b) -> 'b L.tb }
class ['a] tb : 'a -> object method tbm : 'a L.ta end
val make_ta : 'a -> 'a L.ta
end
=
struct
type 'a ta = { tam : 'b. ('a -> 'b) -> 'b L.tb }
let make_ta : 'a -> 'a L.ta = fun a -> { tam = fun f -> new L.tb (f a)}
class ['a] tb x = object method tbm : 'a L.ta = L.make_ta x end
end;;
module rec L :
sig
type 'a ta = { tam : 'b. ('a -> 'b) -> 'b L.tb; }
class ['a] tb : 'a -> object method tbm : 'a L.ta end
val make_ta : 'a -> 'a L.ta
end
# let q = new L.tb 123;;
val q : int L.tb = <obj>
# let w = q#tbm.L.tam string_of_int;;
val w : string L.tb = <obj>
#
(it really works -- the map is applied, the
object is created. I've checked it with more
extended types that allowed me to examine
the contents of such a great container.)
$ ocaml
Objective Caml version 3.12.1+rc1
# module rec L
:
sig
type 'a ta = < tam : 'b. ('a -> 'b) -> 'b L.tb >
class ['a] tb : 'a -> object method tbm : 'a L.ta end
val make_ta : 'a -> 'a L.ta
end
=
struct
type 'a ta = < tam : 'b. ('a -> 'b) -> 'b L.tb >
let make_ta : 'a -> 'a L.ta = fun a ->
object method tam : 'b. ('a -> 'b) -> 'b L.tb =
fun f -> new L.tb (f a)
end
class ['a] tb x = object method tbm : 'a L.ta = L.make_ta x end
end;;
Error: In the definition of L.tb, type 'a L.ta should be 'b L.ta
#
Maybe there is a problem with type "ta" in the second piece,
because record is "concrete" type, but the object type is just
a list of their methods. But I can't check it successfully: trying
to wrap occurences of "tb" with "type 'a id = Id of 'a" (and removing
"ta" at all) does not help, just yields different types in error
"In the definition of .., type .. should be ..".
Please help me. Any ideas are highly appreciated.
next reply other threads:[~2011-09-07 21:29 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-09-07 21:29 Dmitry Grebeniuk [this message]
2011-09-07 21:44 ` Jacques Garrigue
2011-09-09 11:14 ` Dmitry Grebeniuk
2011-09-09 13:50 ` Jacques Garrigue
2011-09-13 4:56 ` Dmitry Grebeniuk
2011-09-13 7:22 ` Gabriel Scherer
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=CAPi0vKXHQ3SyChtphJ7OAtAnDNK5TpfXqq_nKBF7aA0nGHovHw@mail.gmail.com \
--to=gdsfh1@gmail.com \
--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