I've going over Type-driven development, and there is a section on a well-typed printf
, where the type is calculated from the first argument which is a format string:
printf : (fmt : String) -> PrintfType (toFormat (unpack fmt))
toFormat
creates a format representation out of a List Char
and PrintfType
creates a function type out of such a format representation. The full code is here: https://github.com/edwinb/TypeDD-Samples/blob/master/Chapter6/Printf.idr
I understand what's going on with code like printf "%c %c" 'a' 'b'
--the type of printf "%c %c
is calculated to be Char -> Char -> String
.
What I don't understand is what happens when the first argument is unknown at run-time. I understand why in general such code should not compile: the format string, and the resulting type, cannot be known at compile-time if they are entered by a user at run-time, but I don't know the actual technical reasoning behind this intuition.
For example:
main : IO ()
main = do fmt <- getLine
c1 <- getChar
c2 <- getChar
printf fmt c1 c2
Results in the following error message:
When checking an application of function Prelude.Monad.>>=:
printf fmt does not have a function type (PrintfType (toFormat (unpack fmt)))
I guess I'm trying to understand this error message. Does Idris treat functions like this as a special case?