caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
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.

             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;
as well as URLs for NNTP newsgroup(s).