Reputation: 1366
I am trying to define a function msg
which will allow printing debug messages using Format
library with an option to control if they displayed or not via debug
flag (set from a command line). Here is my naive first attempt:
let debug = ref false
let msg =
let open Format in
(if !debug then fprintf err_formatter else ifprintf err_formatter)
Unfortunately, this does not work, giving me the following error message:
Error: The type of this expression,
('_a, Format.formatter, unit) format -> '_a,
contains type variables that cannot be generalized
What am I doing wrong? Thanks!
Upvotes: 1
Views: 39
Reputation: 66818
This is the value restriction. You can solve it by "eta expansion":
let msg x =
let open Format in
if !debug then fprintf err_formatter x
else ifprintf err_formatter x
Briefly stated, the value restriction avoids unsound behavior by prohibiting the generalization (treatment as fully polymorphic) of anything other than simple values. Your definition for msg
is not a simple value. After eta expansion, the definition is a simple value (a lambda). You can read more here: Jacques Garrigue, Relaxing the Value Restriction.
The new code works for me:
# let debug = ref true
val debug : bool ref = {contents = true}
# let msg x =
let open Format in
if !debug then fprintf err_formatter x
else ifprintf err_formatter x;;
val msg : ('a, Format.formatter, unit) format -> 'a = <fun>
# let open Format in
msg "%d " 1; msg "%s" "red rose that I mean";
pp_print_flush err_formatter ();;
1 red rose that I mean- : unit = ()
#
Upvotes: 1