<?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="2002/07/0b573ce0f42e95b4d4fbedbd027299d1"
  from="Alain Frisch &lt;frisch@c...&gt;"
  author="Alain Frisch"
  date="2002-07-28T20:15:02"
  subject="Re: [Caml-list] equi-recursive Fold isomorphism"
  prev="2002/07/fd3e6d80be919abc06bcfd0ee2ffadda"
  next="2002/07/2ed44fafb26311014d214ea830da4a23"
  prev-in-thread="2002/07/d6cc835c30bdf5961ac017a3513d4c19"
  prev-thread="2002/07/31df5f956e055f23defa7f42b31cd382"
  next-thread="2002/07/0cb29bb0ea374d69ebccf8accd5a096d"
  root="../../"
  period="month"
  listname="caml-list"
  title="Archives of the Caml mailing list">

<thread subject="[Caml-list] equi-recursive Fold isomorphism">
<msg 
  url="2002/07/b44d83525a337150d2d807ee742cdfac"
  from="John Max Skaller &lt;skaller@o...&gt;"
  author="John Max Skaller"
  date="2002-07-27T17:32:25"
  subject="[Caml-list] equi-recursive Fold isomorphism">
<msg 
  url="2002/07/4f9bb8f68563eae0df616c5312061cd5"
  from="Alain Frisch &lt;frisch@c...&gt;"
  author="Alain Frisch"
  date="2002-07-27T19:44:01"
  subject="Re: [Caml-list] equi-recursive Fold isomorphism">
<msg 
  url="2002/08/53ed9625fb1f595602c7030ddf5acc8e"
  from="John Max Skaller &lt;skaller@o...&gt;"
  author="John Max Skaller"
  date="2002-08-01T14:49:45"
  subject="[Caml-list] Question about distribution">
<msg 
  url="2002/08/214fa7d010269acc80ff246b88085cea"
  from="Xavier Leroy &lt;xavier.leroy@i...&gt;"
  author="Xavier Leroy"
  date="2002-08-01T15:48:47"
  subject="Re: [Caml-list] Question about distribution">
</msg>
<msg 
  url="2002/08/3120d6d86c63690a934a6e153bbab64f"
  from="Daniel de Rauglaudre &lt;daniel.de_rauglaudre@i...&gt;"
  author="Daniel de Rauglaudre"
  date="2002-08-03T17:35:36"
  subject="Re: [Caml-list] Question about distribution">
</msg>
</msg>
<msg 
  url="2002/07/d6cc835c30bdf5961ac017a3513d4c19"
  from="John Max Skaller &lt;skaller@o...&gt;"
  author="John Max Skaller"
  date="2002-07-28T01:46:42"
  subject="Re: [Caml-list] equi-recursive Fold isomorphism">
<msg 
  url="2002/07/0b573ce0f42e95b4d4fbedbd027299d1"
  from="Alain Frisch &lt;frisch@c...&gt;"
  author="Alain Frisch"
  date="2002-07-28T20:15:02"
  subject="Re: [Caml-list] equi-recursive Fold isomorphism">
</msg>
</msg>
</msg>
</msg>
</thread>

<contents>
On Sun, 28 Jul 2002, John Max Skaller wrote:

&gt; Hmmm: Ocaml 3.04+15 with -rectypes
&gt;
&gt;
&gt; # let rec x = (1,(1,(1,x)));;
&gt; val x : int * (int * (int * 'a)) as 'a =
&gt;  ....
&gt;
&gt; Seem like Ocaml doesn't minimise the type, but:
&gt;
&gt;
&gt; let rec y = (1,y);;
&gt;
&gt; x = y;;
&gt;
&gt; Works correctly (so it knows the two types are comparable).
&gt; Interestingly, the answer is false

Are you sure ?  It seems that the comparison doesn't terminate,
as expected (as it does not consume memory). The manual
says:
&lt;&lt;
Equality between cyclic data structures may not terminate.
&gt;&gt;


: both data structures
&gt; consist of an infinite stream of 1's, represented by
&gt; cycles of distinct lengths. No item by item comparison
&gt; could reveal any distinction: the infinite tree expansions
&gt; of the data structures are the same. Is Ocaml's answer correct?

As you know, to implement the comparison between cyclic values with the
expected behaviour, one has to use a coinductive algorithm with some kind
of memoization. This would be much slower for the non-cyclic case, and
many people expect a fast generic compare function. I would like to say
that you can always take the code in byterun/compare.c and implement your
own equirecursive generic comparison in C, but this is actually not
possible (you need the Is_young and Is_in_heap macros that are not
available). Using the mentioned Recurse module, you could do:

module I = struct
  type 'a t = Int of int | Pair of 'a * 'a

  let map f = function
    | Int i -&gt; Int i
    | Pair (a,b) -&gt; Pair (f a, f b)

  let equal f x y =
    match (x,y) with
      | (Int i, Int j) when i = j -&gt; ()
      | (Pair (a1,b1), Pair (a2,b2)) -&gt; f a1 a2; f b1 b2
      | _ -&gt; raise Recursive.NotEqual

  let iter f x = ignore (map f x)
  let hash f x = Hashtbl.hash (map f x)
  let deep = 4
end

module X = Recursive.Make(I)


let cons x = let n = X.make () in X.define n x; n
let recurs f = let n = X.make () in X.define n (f n); n
let int' i = I.Int i
let int i = cons (int' i)
let pair' a b = I.Pair (a,b)
let pair a b = cons (pair' a b)

let x = recurs (fun x -&gt; pair' (int 1) (pair (int 1) (pair (int 1) x)))
let y = recurs (fun y -&gt; pair' (int 1) y)

let x = X.internalize x and y = X.internalize y
let () = Printf.printf "%i;%i;%b\n" (X.id x) (X.id y) (x = y)


(the equility test is specified by Recurse to run in constant time)


Side-note: be careful if you implement a language with subtyping and both
recursive types and recursive (cyclic) values. Indeed, the usual
equi-recursive definition of subtyping is not sound if you allow cyclic
values. For instance, the algorithm would say that the type ('a * 'a) as
'a is empty, even though it is inhabited by values.


-- Alain

-------------------
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>

