<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE message PUBLIC
  "-//MLarc//DTD MLarc output files//EN"
  "../../mlarc.dtd"[
  <!ATTLIST message
    listname CDATA #REQUIRED
    title CDATA #REQUIRED
  >
]>

  <?xml-stylesheet href="../../mlarc.xsl" type="text/xsl"?>


<message 
  url="2003/07/2ad4fe2fc6657cf9aca64ef6fda489ec"
  from="Jacques Garrigue &lt;garrigue@k...&gt;"
  author="Jacques Garrigue"
  date="2003-07-22T22:06:49"
  subject="Re: [Caml-list] Variant parameterized method?"
  prev="2003/07/7347ef3d79f516ef8692babe85c8791a"
  next="2003/07/e85ce98c80b46bc247f9dbfe9e5f0e10"
  prev-in-thread="2003/07/7347ef3d79f516ef8692babe85c8791a"
  next-in-thread="2003/07/e85ce98c80b46bc247f9dbfe9e5f0e10"
  prev-thread="2003/07/f4f0c2155e99d8e24366c19287802309"
  next-thread="2003/07/29d3d4246f320c31566fbe65671742e3"
  root="../../"
  period="month"
  listname="caml-list"
  title="Archives of the Caml mailing list">

<thread subject="[Caml-list] Variant parameterized method?">
<msg 
  url="2003/07/7347ef3d79f516ef8692babe85c8791a"
  from="Brian Hurt &lt;brian.hurt@q...&gt;"
  author="Brian Hurt"
  date="2003-07-22T20:11:01"
  subject="[Caml-list] Variant parameterized method?">
<msg 
  url="2003/07/2ad4fe2fc6657cf9aca64ef6fda489ec"
  from="Jacques Garrigue &lt;garrigue@k...&gt;"
  author="Jacques Garrigue"
  date="2003-07-22T22:06:49"
  subject="Re: [Caml-list] Variant parameterized method?">
<msg 
  url="2003/07/e85ce98c80b46bc247f9dbfe9e5f0e10"
  from="Brian Hurt &lt;brian.hurt@q...&gt;"
  author="Brian Hurt"
  date="2003-07-22T22:35:48"
  subject="Re: [Caml-list] Variant parameterized method?">
</msg>
</msg>
</msg>
</thread>

<contents>
From: Brian Hurt &lt;brian.hurt@qlogic.com&gt;

&gt; What I want to do is write a class interface like:
&gt; 
&gt; class virtual ['a] foo :
&gt; object
&gt; 	method virtual doit : 'a
&gt; 	method map : 'b. ('a -&gt; 'b) -&gt; 'b foo
&gt; end
&gt; 
&gt; The map function returns a new foo (not necessarily a new member of 
&gt; whatever derived from foo class the function is actually being called on) 
&gt; parameterized on the variant type.

This precise type is not admissible in the ocaml type system.
In ocaml recursive types must be regular: only 'a foo may occur in the
expansion of 'a foo.

This problem is discussed in an answer to PR#1730 in the caml bug
database.
This can be solved by introducing an explicit wrapper.

I give two versions of the code: with a polymorphic reference and with
a recursive modules. They are strictly equivalent: one is not safer
than the other (at least currently).

(* polymorphic reference *)
type 'a c0 = C of &lt; map : 'b. ('a -&gt; 'b) -&gt; 'b c0 &gt;

type m = {mutable new_c : 'a. 'a -&gt; 'a c0}
let m = {new_c = fun _ -&gt; failwith "new_c"}

class ['a] c (x : 'a) = object
  method map : 'b. ('a -&gt; 'b) -&gt; 'b c0 = fun f -&gt; m.new_c (f x)
end
let () = m.new_c &lt;- fun x -&gt; C (new c x)

(* recursive module *)
module rec M : sig
  class ['a] c : 'a -&gt; object
    method map : ('a -&gt; 'b) -&gt; 'b M.c_t
  end
  type 'a c_t = C of 'a c
end = struct
  class ['a] c (x : 'a) = object (_ : _ #M.c)
    method map = fun f -&gt; M.C (new M.c (f x))
  end
  type 'a c_t = C of 'a c
end

Not that the fact the result of #map is a ['b c_t] rather than a ['b
c] is not a practical problem: you can just write
  let C x' = x#map f
If you prefer a [(x#map f).c] notation, use a one-field record rather
than a one constructor sum.

If you think (as I do) that all these examples are just too
complicated in practice, there is a simpler way to go:
only define a fold method in your class, and define map itself out of
the class.

Jacques Garrigue

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners

</contents>

</message>

