Yes. The pipe operator does what you think it does. However, printfn
is "special" that it takes a kind of "formattable string" (there are different kinds of these) and the compiler does its magic only when the format string appears as a direct argument.
In other words, your "Hello"
in the first example is not really a string, it is a Printf.TextWriterFormat
object, magically created by the compiler.
Still, you can do what you want by using an explict format string. This approach you'll see quite a bit in real-world code:
"Hello" |> printfn "%s"
Here, %s
means: give me a string. The magic of F# in this case again takes the format string, here "%s"
, this time with an argument of type string
, and turns it into a function.
Note 1: that this "surprise effect" is being considered and the community works towards adding a printn
function (i.e., without the f
which stands for format
) to just take a simple string: https://github.com/fsharp/fslang-suggestions/issues/1092
Note 2: if you do want to pass arguments to printfn
around, you can make the type explicit, but this is done very rarely:
let x = Printf.TextWriterFormat<unit> "Hello"
x |> printfn // now it's legal
Note 3: you might wonder why the compiler doesn't apply its magic to the lh-side of |>
as well. The reason is that |>
is not an intrinsic to the compiler, but just another overridable operator. Fixing this is therefor technically very hard (there can be any amount of operators on the lh-side), though it has been considered at certain times.
Other alternative
In the comments, the OP suggested that he/she/they didn't like the idea of having to use printfn "%i"
and the like, and ended up writing print
, printInt
etc functions.
If you go that route, you can write your code in a class with only static methods, while using function-style naming. Then just open the static type (this is a new feature in F# 6).
module MyPrinters =
// create a static type (no constructors)
type Printers =
static member print x = printfn "%s" x // string
static member print x = printfn "%i" x // integer
static member print x = printfn "%M" x // decimal
static member print x = printfn "%f" x // float
module X =
// open the static type
open type MyPrinters.Printers
let f() = print 42
let g() = print "test"
let print = fun msg -> printf "%s" msg
Probably that will regain integration of the language. – Animadvert