leads to the following error on the c (fun () -> ()) expression:
File "tst.ml", line 1, characters 27-43:
Error: This expression has type f:(unit -> (unit -> unit) -> 'a) -> 'a
but an expression was expected of type unit
Without the ~, there is no error. How is the ~ messing things up?
This is fixed by passing the argument with an explicit label:
let c ~f = f() in let () = c ~f:(fun () -> ()) in ()
The reason you can’t omit the label is because the application of c is not considered to be fully applied. This can be a surprise when the return type of a function with labelled arguments is a type variable, which is the case for c.
To make it quite clear: when you pass (fun () -> ()) the return type of c is being inferred as a function type, and the argument is being passed to that function.