In its simplest form, I have a writer type and a dispatching handler like this:
type ('a, 'b) writer = ((unit -> 'a) -> 'b)type ('a, 'b) handler = { handle : 'a -> (string -> 'a -> 'b, 'b) writer }
Then I wish to define a family of handlers that ultimately call the writer's continuation. In the very simplest form, a handler might be expressed as:
let f = { handle = fun a k -> write_int_field "f" a k }which would have type "(int, 'a) handler" as desired. (In the real implementation, there will be more than one handler, hence the need for the record.) However, I wish to define a family of handlers that all share common implementation, so I define a helper function (again, vastly simplified):
let helper name wf = { handle = fun a k -> wf name a k } let f = helper "f" write_int_fieldHowever, here the type of "f" is now "('int, '_a) handler" and fails to unify with the desired type expressed in the interface.
Now, I could get around this by making "f" be a function that when evaluated returns the result of the helper. However, I'm trying to avoid that because in the real implementation, the work of the helper is somewhat expensive and should only be performed once. An alternate solution can be achieved by pushing the universal qualifier for the result type down into the handler:
type 'a handler = { handle : 'b . 'a -> (string -> 'a -> 'b, 'b) writer }
However, this doesn't allow me to define the helper function as before: let helper name wf = { handle = fun a k -> wf name a k };; ^^^^^^^^^^^^^^^^^^^^^^ This field value has type 'a -> (string -> 'a -> 'b, 'b) writer which is less general than 'c. 'd -> (string -> 'd -> 'c, 'c) writerI am forced into reworking the helper parameter function, wf, to also become a record in order for it to be universally qualified:
type 'a field_handler = { write_field : 'b . string -> 'a -> (unit -> string -> 'a -> 'b) -> 'b }
This works: let helper name wf = { handle = fun a k -> wf.write_field name a k } let f = helper "f" write_int_fieldHere "f" has type "int handler" as desired, although this solution seems somewhat round-about, and was difficult to arrive at. Can anyone suggest another approach that prevents the dreaded underscores? (Note that using objects instead of records exhibits the exact same behavior.)
Warren Harris Metaweb Technologies
smime.p7s
Description: S/MIME cryptographic signature
_______________________________________________ Caml-list mailing list. Subscription management: http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list Archives: http://caml.inria.fr Beginner's list: http://groups.yahoo.com/group/ocaml_beginners Bug reports: http://caml.inria.fr/bin/caml-bugs