f# - 如何使用 printf 自定义自定义类型的输出?

标签 f# printf string-formatting f#-interactive

我已经阅读了大量的 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;}

最佳答案

看起来在 F# 2.0 中执行此操作的正确方法是使用 StructuredFormatDisplay 属性,例如:

[<StructuredFormatDisplay("hello {a}")>]
type myType = {a: int}

在这个例子中,不是默认的 {a = 42;} , 你会得到 hello 42 .

这对于对象、记录和联合类型的工作方式相同。虽然模式必须是格式 "PreText {PropertyName} PostText" (PreText 和 PostText 是可选的),这实际上比 ToString() 更强大因为:
  • 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" .

    关于f# - 如何使用 printf 自定义自定义类型的输出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/791706/

    相关文章:

    c - Re Legacy 代码 : format ‘%d’ expects argument of type ‘int’ , 但参数 3 的类型为 ‘long unsigned int’ [-Wformat]

    c - C 中 printf 可打印的最大字符数

    (s)printf 的 C++ 标准替代品

    F#:消除 Map/Reduce/Filter 中的冗余

    python - FSharp 运行我的算法比 Python 慢

    F#:使用字符串组合 sprintf -> unit 函数以允许格式化

    c - 当一个参数通过另一个参数的引用传递时,printf 如何处理它的参数

    f# - 管还是不管?

    selenium-webdriver - Canopy - 使用选择列表

    database - 从 FORMAT 输出到字符串?