2012/4/12 Alain Frisch > On 04/12/2012 04:16 PM, Philippe Veber wrote: > >> Isn't this a good use case for polymorphic variants too ? >> > > I don't see how to use polymorphic variants here. The message bus itself > need to provide functions like: > > val dispatch: message -> unit > val register_listener: (message -> unit) -> unit > > > How do you define the message type without having access to all possible > message constructors? I reckon you can't, but I mistakenly thought you could at least define the bus without writing the full message type: module Bus : sig type 'a t val create : unit -> 'a t val dispatch : 'a t -> 'a -> unit val register : 'a t -> ('a -> unit) -> unit end = struct type 'a t = ('a -> unit) list ref let create () = ref [] let dispatch bus msg = List.iter (fun f -> f msg) !bus let register bus f = bus := f :: !bus end let bus = Bus.create () let () = Bus.register bus (function `a -> print_char 'a') let () = Bus.register bus (function `b n -> print_int n) However this is not a legal program: let () = Bus.register bus (function `b n -> print_int n);; ^^^^ Error: This pattern matches values of type [< `b of 'a ] but a pattern was expected which matches values of type [< `a ] These two variant types have no intersection Well, I mentionned polymorphic variants because you can at least define listeners without knowing the full message type and even reuse them for buses with different message types. So you have a certain flexibility, compared to monomorphic types. But ok, maybe the remark wasn't even worth 2 cents :o). Cheers, ph.