> the types required to apply the function are statically analyzed from the format string.
Not so, in that Haskell package:
Prelude Text.Printf> printf "%d\n" 1
1
Prelude Text.Printf> printf "%d\n"
*** Exception: printf: argument list ended prematurely
Prelude Text.Printf> printf "%d\n" 0.5
*** Exception: printf: bad formatting char 'd'
Prelude Text.Printf> printf "%d\n" 1 2
1
*** Exception: printf: formatting string ended prematurely
It could certainly be done with TH/QQ. I'm not sure, offhand, if there is already a package to that effect.