我已经阅读了很多 Expert F#,正在构建一个实际的应用程序。在调试时,我已经习惯于传递这样的fsi命令,以便在repl窗口中清晰可见:
fsi.AddPrinter(fun (x : myType) -> myType.ToString())
我想扩展它以使用printf格式化程序,所以我可以输入例如。
printf "%A" instanceOfMyType
并控制自定义类型的输出。本书暗示可以做到这一点(第93页,“可以扩展通用结构格式以适用于任何用户定义的数据类型, F#网站上的一个主题“),但我没有找到任何关于如何实现这一点的参考。有谁知道怎么做?它甚至可能吗?
修改
我应该包含一个代码示例,它是我正在处理的记录类型,例如
type myType =
{a: int}
override m.ToString() = "hello"
let t = {a=5}
printfn "%A" t
printfn "%A" (box t)
两个印刷语句都会产生:
{a = 5;}
答案 0 :(得分:37)
在F#2.0中执行此操作的正确方法似乎是使用StructuredFormatDisplay
属性,例如:
[<StructuredFormatDisplay("hello {a}")>]
type myType = {a: int}
在此示例中,您将获得{a = 42;}
而不是默认hello 42
。
对于对象,记录和联合类型,它的工作方式相同。虽然模式必须是格式"PreText {PropertyName} PostText"
( PreText 和 PostText 是可选的),但这实际上比ToString()
更强大,因为:< / p>
PropertyName
可以是任何类型的属性。如果它不是字符串,那么它也将受到结构化格式的限制。 Don Syme's blog给出了以这种方式递归格式化树的示例。
它可能是计算属性。所以你实际上可以让ToString()
为记录和联合类型工作,尽管是以相当全面的方式:
[<StructuredFormatDisplay("{AsString}")>]
type myType =
{a: int}
override m.ToString() = "hello"
member m.AsString = m.ToString() // a property that calls a method
顺便说一下,如果您拨打ToString()
而不是printfn "%O"
,将始终使用printfn "%A"
(即使是记录和联合类型)。
答案 1 :(得分:4)
无论如何,在CTP上,我看到了
type MyType() =
override this.ToString() = "hi"
let x = new MyType()
let xs = Array.create 25 x
printfn "%A" x
printfn "%A" xs
在VFSI窗口中进行评估时,我会做什么,以及
x;;
xs;;
也打印得很好。所以,我想我不清楚这与期望的有何不同?
答案 2 :(得分:-2)
如果重写ToString方法,那应该这样做。