Converting non-literal strings to ('a...'f) CamlinternalFormatBasics.format6

Hi,

the OCaml manual says:

format_of_string can not convert a string argument that is not a literal. If you need this functionality, use the more general Scanf.format_from_string function.

and

Scanf.format_from_string s fmt converts a string argument to a format string, according to the given format string fmt.

  • Since 3.10
  • Raises Scan_failure if s, considered as a format string, does not have the same type as fmt.

I tried

# let str = "abc";;

val str : string = "abc"

# Scanf.format_from_string str "%s";;
Exception:
Stdlib.Scanf.Scan_failure
 "bad input: format type mismatch between \"abc\" and \"%s\"".

My need is to insert a string (with no %'s) between two given format strings, i.e. something like

let insert str = 
  given_fmt1 ^^ (Scanf.format_from_string str "%s") ^^ given_fmt2

val insert : string -> ('a,...'f) CamlinternalFormatBasics.format6

What am I missing?

To provide some context for my question:

I was given an OCaml module for which I do not have the source code. To generate an error message, I have access to the function

M.error_fmt : string -> (...)format6;

which accepts only a string literal and inserts it between two format6 values ​​(accessible by the functions M.error_head and M.error_foot), returning a format6.

The only and weird way to pass an error message to the module, is building a format6 (using M.error_fmt or a custom function) and passing it to M.error_raise.

I need to write a more general function
gen_error_fmt str =
(error_fmt_head ...) ^^ (conversion_of str) ^^ (error_fmt_foot ...)
that accepts non-literal strings as well.

Something like this?

let insert fmt1 str fmt2 =
  fmt1 ^^ Scanf.format_from_string str "" ^^ fmt2

The second argument passed to Scanf.format_from_string should have the same formatting “structure” as the first argument (number, type, and order of formatting indications). If the first argument is a constant string (no formatting indicators at all), then you can use the empty string, or any other string without formatting indications, as second argument.

Cheers,
Nicolas