为什么Fam的printf中的%A说明符在OCaml的printf中不存在?

asa*_*afc 8 f# ocaml

在F#中printf有格式说明符%A,它可以传入任何F#类型,并且它将被评估和打印.

举个例子:

type Result<'a> =
    | Failure
    | Success of 'a       

printf "%A" (Success "hello") // prints out 'Success "hello"'
Run Code Online (Sandbox Code Playgroud)

显然,Result<'a>它不是内置类型.

我可以在OCaml中声明一个类似的类型,但是没有等效的说明符Printf.printf- 相反,我必须实现我自己的string_of_result函数,并使用%s格式字符串中的说明符.此外,由于这是一个多态类型,我将不得不创建一个可以处理任何类型实例的非直接函数'a.

我的问题是 - 为什么OCaml缺少这个方便的说明符?是因为没有动力实施它吗?是因为有一些缺乏引擎盖的魔力,这就是F#中的那个吗?

scr*_*wtp 7

我会说"缺乏引擎盖下的魔力"可能就是原因.

在F#中,%A说明符将打印延迟到基于反射的打印机 - 它使用运行时类型信息来遍历和打印值.在该过程中使用的反射API非常类似于.NET.同时方便,它也是一个相对昂贵的机制 - 如果你可以使用更具体的机制,它不应该用作毯子说明书.

据我所知,OCaml没有可以在这里使用的相应反射功能.也许还有另一种机制可以让你实现一个通用的打印 - 但我对OCaml的内部结构并不熟悉.


gsg*_*gsg 7

在OCaml中执行此操作的常用方法是使用说明%a符,并写入(或派生)打印机result以传递给它.

这可能看起来像这样:

type 'a result =
  | Success of 'a
  | Failure
[@@deriving show]

Format.printf "%a" (pp_result Format.pp_print_string) (Success "hello")
Run Code Online (Sandbox Code Playgroud)

其中pp_result已被所生成的deriving子句.请注意,pp_result它将格式化函数作为参数,用于打印任何'as.

OCaml在编译期间(几乎)完全擦除类型,因此反射不能用于实现F#中的自动打印功能.无论如何,不​​清楚反射在抽象类型的语言中是否能够很好地工作.