Version française
Home     About     Download     Resources     Contact us    
Browse thread
Bug? Constraints get ignored in methods
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ 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