Browse thread
Bug? Constraints get ignored in methods
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: | 2009-04-01 (15:57) |
From: | Goswin von Brederlow <goswin-v-b@w...> |
Subject: | Re: [Caml-list] Bug? Constraints get ignored in methods |
Martin Jambon <martin.jambon@ens-lyon.org> writes: > Would the following work for you: No. Not just like this. > type 'a linked = { > data : 'a; > mutable next : < > linked option > } > (* constraint 'a = < .. > *) > > let create data next = { > data = data; > next = (next :> < > linked option) > } > > let set_next x y = > x.next <- (y :> < > linked option) > > > class s = > object > method s = "abc" > end > > class i = > object > method i = 123 > end class s and i have no access to the linked type. You could not remove a class s or i from the linked structure in O(1) from within class s or i. So linked would have to handle any function that might require altering the linked structure and pass parts of it to its data. But data is an unknown type so no method of it can be called. I would first need a class type containing the common functionality. Then 'a needs to be constraint to a superset of that class and next has to be an linked option of that class. Only then can the linked type call methods of its data. Your suggestion has one benefit though. By using a record + normal functions instead of a class one avoids a recursively constraint method, which ocaml doesn't like. MfG Goswin ---------------------------------------------------------------------- PS: below is a completly object free solution. It comes at the cost of requireing Obj.magic though. But its evilness is contained in M alone and can't escape. Not sure yet what way I will go. module M : sig type 'a fn = { to_string : 'a -> string; alter : 'a -> 'a } type 'a base val make : 'a -> 'a fn -> 'a base val to_string : 'a base -> string val alter : 'a base -> unit val iter : ('a base -> unit) -> unit end = struct type 'a fn = { to_string : 'a -> string; alter : 'a -> 'a } type 'a base = { mutable next : unit base; mutable prev : unit base; mutable data : 'a; fn : 'a fn } let unit_fn = { to_string = (fun () -> ""); alter = (fun () -> ()) } let rec head = { next = head; prev = head; data = (); fn = unit_fn } let make data fn = let e = { next = head; prev = head.prev; data = data; fn = fn } in head.prev.next <- Obj.magic e; head.prev <- Obj.magic e; e let to_string x = x.fn.to_string x.data let alter x = x.data <- x.fn.alter x.data let iter (fn : 'a base -> unit) = let fn : unit base -> unit = Obj.magic fn in let rec loop = function x when x == head -> () | x -> fn x; loop x.next in loop head.next end let string_fn = { M.to_string = (fun s -> s); M.alter = (fun s -> s ^ "+") } let int_fn = { M.to_string = (fun i -> Printf.sprintf "%d" i); M.alter = (fun i -> i +1) } let s = M.make "s" string_fn let i = M.make 1 int_fn let _ = M.iter (fun x -> Printf.printf "%s\n" (M.to_string x)) let _ = M.iter M.alter let _ = M.iter (fun x -> Printf.printf "%s\n" (M.to_string x)) => s 1 s+ 2