strange behavior of the object type-checker

From: Pierre Boulet (Pierre.Boulet@lifl.fr)
Date: Thu Sep 09 1999 - 18:34:19 MET DST


To: caml-list@inria.fr
Subject: strange behavior of the object type-checker
From: Pierre Boulet <Pierre.Boulet@lifl.fr>
Date: 09 Sep 1999 18:34:19 +0200

dear ocamllers,

I have finally decided to give a try to the object subsystem of ocaml
and I have stumbled on something very strange (for me, at least).

In the code I present below, after some parametric class creation, I
try to execute some method of an object. Three *successive* tries give
three *different* results: two different typing error messages and
finally success.

This code has been tested with ocaml 2.02 and the cvs version of
yesterday (8 sept.), ocaml 2.02+3. They give the same result.

My aim is to define a graph class which implements simple graph
algorithms such as depth first scanning. Anyway, here is the code.

class ['e] node g n0 =
  object (self)
    val mutable mark = true (* a boolean to handle cycles *)
    method mark = mark
    method set_mark = mark <- true
    method unset_mark = mark <- false

    val mutable edges = ([] : 'e list) (* outgoing edges *)
    method edges = edges
    method add_edge e = edges <- e::edges
    initializer g#add_node self (* registration into the graph *)

    val n = n0 (* dummy printing *)
    method n = n
    method draw =
      Printf.printf "node: %i\n" n

    method iter fn fe = (* depth first iteration *)
      if self#mark then
         begin
          fn self;
                self#unset_mark;
                List.iter (fun e -> e#iter fn fe) edges
              end
  end;;

class ['n] edge g from_init towards_init =
  object (self)
    val mutable mark = true (* a boolean to handle cycles *)
    method mark = mark
    method set_mark = mark <- true
    method unset_mark = mark <- false

    val from = (from_init : 'n)
    val towards = (towards_init : 'n)
    method from = from
    method towards = towards
    initializer g#add_edge self (* registration into the graph *)
    initializer from#add_edge self (* registration into the from node *)

    method draw = (* dummy printing *)
      Printf.printf "edge: %i->%i\n" from#n towards#n

    method iter fn fe = (* depth first iteration *)
      if self#mark then
         begin
          fe self;
                self#unset_mark;
          towards#iter fn fe
          end
  end;;

class ['n,'e] graph =
  object (self)
    val mutable nodes = ([] : 'n list) (* list of nodes *)
    method nodes = nodes
    val mutable start_node = (None : 'n option)
    method start_node = start_node
    method set_start_node n = start_node <- Some n
    method add_node n =
      nodes <- n::nodes;
      match nodes with
        | [n] -> self#set_start_node n
        | _ -> ()

    val mutable edges = ([] : 'e list) (* list of edges *)
    method edges = edges
    method add_edge e = edges <- e::edges

    method set_marks =
      List.iter (fun n -> n#set_mark) nodes;
      List.iter (fun e -> e#set_mark) edges

    method iter (fn : 'n -> unit) (fe : 'e -> unit) = (* depth first iteration *)
      match start_node with
        | None -> failwith "set start node first"
        | Some n ->
            self#set_marks;
            (n#iter fn fe : unit)
  end;;

let g = new graph;;
g#iter (fun n -> n#draw) (fun e -> e#draw);;
let n1 = new node g 1;;
g#iter (fun n -> n#draw) (fun e -> e#draw);;
(* until now, everything goes fine *)
let e11 = new edge g n1 n1;;
g#iter (fun n -> n#draw) (fun e -> e#draw);;
(* returns:
        Characters 17-18:
        This expression has type 'a edge node as 'a
        It has no method draw
*)
g#iter (fun n -> n#draw) (fun e -> e#draw);;
(* returns:
        Characters 0-1:
        This expression has type
          (('a edge as 'b) node as 'a, ('c node as 'd) edge as 'c) graph
        It has no method iter
*)
g#iter (fun n -> n#draw) (fun e -> e#draw);;
(* returns as expected:
        node: 1
        edge: 1->1
        - : unit = ()
*)

So what happens? It seems that adding an edge to the graph unsettles
the type checker...

any thought?

-- 
Pierre.



This archive was generated by hypermail 2b29 : Sun Jan 02 2000 - 11:58:25 MET