module Univ = struct type t = .. let id = let id = ref 0 in fun () -> incr id ; !id module Embed (M : sig type t end) = struct type t += E of M.t let wrap m = E m let read = function E m -> Some m | _ -> None let new_property () = let id = id () in let set t v = Hashtbl.replace t id @@ wrap v in let get t = Hashtbl.find_opt t id |> Fun.flip Option.bind read in (set, get) end end module IntWrapper = Univ.Embed(Int) module StringWrapper = Univ.Embed(String) let and_null = Hashtbl.create 16 let or_watt = Hashtbl.create 16 let name = StringWrapper.new_property () let age = IntWrapper.new_property () let money = IntWrapper.new_property () let get t (set, get) = get t let set t (set, get) x = set t x let () = set and_null name "and Null" let () = set and_null age 28 let () = set and_null money 20 let () = set or_watt name "or Watt" let () = set or_watt age 28 let () = set or_watt money 100