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.
--
Caml-list mailing list. Subscription management and archives:
https://sympa-roc.inria.fr/wws/info/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs