Version française
Home     About     Download     Resources     Contact us    
Browse thread
strange behavior of the object type-checker
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Pierre Boulet <Pierre.Boulet@l...>
Subject: strange behavior of the object type-checker
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.