I've read through a good chunk of Expert F# and am working on building an actual application. While debugging, I've grown accustomed to passing fsi commands like this to make things legible in the repl window:
fsi.AddPrinter(fun (x : myType) -> myType.ToString())
I would like to extend this to work with the printf formatter, so I could type e.g.
printf "%A" instanceOfMyType
and control the output for a custom type. The book implies that this can be done (p 93, "Generic structural formatting can be extended to work with any user-defined data types, a topic covered on the F# website"), but I have failed to find any references as to how to actually accomplish this. Does anyone know how? Is it even possible?
Edit:
I should have included a code sample, it's a record type that I'm dealing with, e.g.
type myType =
{a: int}
override m.ToString() = "hello"
let t = {a=5}
printfn "%A" t
printfn "%A" (box t)
both print statements yield:
{a = 5;}
If you override ToString method, that should do.
Hmm... I vaguely recall some changes to this, but I forget if they happened before or after the CTP (1.9.6.2).
In any case, on the CTP, I see that
when evaluated in the VFSI window does what I would want, and that
also prints nicely. So, I guess I am unclear how this differs from what is desired?
It looks like the Right Way to do this in F# 2.0 is by using the
StructuredFormatDisplay
attribute, for example:In this example, instead of the default
{a = 42;}
, you would gethello 42
.This works the same way for object, record, and union types. And although the pattern must be of the format
"PreText {PropertyName} PostText"
(PreText and PostText being optional), this is actually more powerful thanToString()
because:PropertyName
can be a property of any type. If it is not a string, then it will also be subject to structured formatting. Don Syme's blog gives an example of recursively formatting a tree in this way.It may be a calculated property. So you could actually get
ToString()
to work for record and union types, though in a rather round-about way:By the way,
ToString()
will always be used (even for record and union types) if you callprintfn "%O"
instead ofprintfn "%A"
.