Bad list syntax -> bad ocamlformat -> bad list
Consider this example of dependency injection via module (inspired by why ocaml):
module type IO = sig
val print_endline : string -> unit
val read_line : unit -> string
end
let program (module Handler : IO) =
let () = Handler.print_endline "Hello World" in
let () = Handler.print_endline "What is your name?" in
let name = Handler.read_line () in
Handler.print_endline ("Hello " ^ name)
let () =
let output = ref [] in
let module TestIO = struct
let print_endline s = output := s :: !output
let read_line () = "Test user"
end in
program (module TestIO);
assert (!output = ["Hello Test user", "What is your name?", "Hello World"])
The last line exhibits an easy error in OCaml if you're very used to other languages: that's not a list of three strings, but a list of one string * string * string tuple, making it a compile-time error as that's incompatible with !output:
19 | assert (!output = ["Hello Test user", "What is your name?", "Hello World"])
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This expression has type 'a * 'b * 'c
but an expression was expected of type string
OK, so you open the file back up, reflexively ocamlformat it, and then change commas to semicolons. Resulting in this line:
assert (!output = [("Hello Test user"; "What is your name?"; "Hello World")])
Which is no longer an error! It compiles! But suspiciously, it compiles with some warnings, and the assertion fails:
$ ocaml o17.ml
File "./o17.ml", line 19, characters 22-39:
19 | assert (!output = [("Hello Test user"; "What is your name?"; "Hello World")])
^^^^^^^^^^^^^^^^^
Warning 10 [non-unit-statement]: this expression should have type unit.
File "./o17.ml", line 19, characters 41-61:
19 | assert (!output = [("Hello Test user"; "What is your name?"; "Hello World")])
^^^^^^^^^^^^^^^^^^^^
Warning 10 [non-unit-statement]: this expression should have type unit.
Exception: Assert_failure ("./o17.ml", 19, 2).
ocamlformat added parentheses to make it clear that we had a tuple, but parentheses are not actually a syntax for tuples - it's commas that create tuples. The result is instead equivalent to begin "Hello Test User"; ... end, so what's created is a list of a single string, and the first two strings are discarded.
With those parentheses removed, the assertions pass.