53

Im puzzled

let test = "aString"

let callMe =
    printfn test

Why isn't this working? Throws below error at compile time:

The type 'string' is not compatible with the type 'Printf.TextWriterFormat<'a>'

This works fine:

printfn "aString"
rid
  • 61,078
  • 31
  • 152
  • 193
CodeMonkey
  • 3,418
  • 4
  • 30
  • 53

3 Answers3

77

That's because the format parameter is not actually a string. It's TextWriterFormat<'T> and the F# compiler converts the string format into that type. But it doesn't work on string variables, because the compiler can't convert the string to TextWriterFormat<'T> at runtime.

If you want to print the content of the variable, you shouldn't even try to use printfn this way, because the variable could contain format specifications.

You can either use the %s format:

printfn "%s" test

Or use the .Net Console.WriteLine():

Console.WriteLine test

Don't forget to add open System at the top of the file if you want to use the Console class.

svick
  • 236,525
  • 50
  • 385
  • 514
  • 1
    I would add that using `Console.WriteLine` in F# code is not idiomatic, and the `printf` version is much more common. – John Palmer Feb 25 '12 at 05:02
  • 1
    Ah ok makes sense if the compiler converts it i guess. Ended up with printfn "%s" test – CodeMonkey Feb 25 '12 at 19:31
  • 6
    you can also do `stdout.WriteLine test` where I guess the only advantage is that it is one char shorter and you don't need to open `System` – Stephen Swensen Feb 26 '12 at 05:44
  • 5
    Makes me wonder why there isn't just a *print* function that does no formatting. I guess it would be easy to define. let print value = printfn "%s" value – jpierson Oct 07 '15 at 02:11
4

In line with what svick said, you might also try this:

let test = "aString"
let callMe = printfn (Printf.TextWriterFormat<_> test)
callMe
Shawn Eary
  • 684
  • 2
  • 7
  • 21
1

In addition to answers below. You may also write like this:

let test = "aString"
let print =
   printfn $"{test}"
Viaceslavus
  • 180
  • 1
  • 8
  • That substitutes `test` as a string variable, as indicated, and produces `aString`, but it doesn't allow for format specifiers in `test`. Change to `let test = " aString %s"` and it produces ` aString %s`. – Stephen Hosking Sep 27 '22 at 22:43