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: | -- (:) |
| 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