2012/4/12 Alain Frisch <alain@frisch.fr>
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.