OCaml has compiler level support for format strings. "%d" and friends get parsed into a GADT at compile time and printf "%d" has type int -> unit
In Haskell PrintfType => type-class magic is used to make printf accept a variable number of arguments. However, the types of those arguments are not checked against the format string (since the format string is just a string). Hence the error happens at runtime and Haskell's printf is effectively untyped.
It is not very hard to implement printf that takes a GADT and and has a proper type (e.g. Int -> String) and there are libraries that do something along these lines (see formatting library on Hackage; there's also a template-haskell based solution that uses a quasi-quoter [fmt|%d\n|]). But I do prefer the elegance of c-style format strings.
Besides OCaml has this out of the box and in standard library while Haskell printf is dangerous and should be avoided. Even C++ is better -- I've seen compilers/linters throwing warnings at me when arguments didn't match the format string. Printing to stdout/stderr shouldn't be hard and shouldn't be something one needs third-party libraries to do nicely. Hence I've put it on the list.
utop # printf "%d\n" "foo!";; Error: This expression has type string but an expression was expected of type int
versus what happens in Haskell:
λ printf "%d\n" "foo" * Exception: printf: bad formatting char 'd'
OCaml has compiler level support for format strings. "%d" and friends get parsed into a GADT at compile time and printf "%d" has type int -> unit
In Haskell PrintfType => type-class magic is used to make printf accept a variable number of arguments. However, the types of those arguments are not checked against the format string (since the format string is just a string). Hence the error happens at runtime and Haskell's printf is effectively untyped.
It is not very hard to implement printf that takes a GADT and and has a proper type (e.g. Int -> String) and there are libraries that do something along these lines (see formatting library on Hackage; there's also a template-haskell based solution that uses a quasi-quoter [fmt|%d\n|]). But I do prefer the elegance of c-style format strings.
Besides OCaml has this out of the box and in standard library while Haskell printf is dangerous and should be avoided. Even C++ is better -- I've seen compilers/linters throwing warnings at me when arguments didn't match the format string. Printing to stdout/stderr shouldn't be hard and shouldn't be something one needs third-party libraries to do nicely. Hence I've put it on the list.