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

时间:2017-04-13 16:19:45

标签: f# ocaml

在F#的printf中,格式说明符%A可以传入任何F#类型,并且会对其进行评估和打印。

举个例子:

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

printf "%A" (Success "hello") // prints out 'Success "hello"'

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

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

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

2 个答案:

答案 0 :(得分:7)

我说&#34;缺乏引擎盖下的魔力&#34;可能是原因。

在F#中,%A说明符将打印延迟到基于反射的打印机 - 它使用运行时类型信息来遍历和打印值。在该过程中使用的反射API非常类似于.NET。虽然它也很方便,但它也是一种比较昂贵的机制 - 如果你能使用更具体的机制,它不应该被用作毯子说明器。

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

答案 1 :(得分:7)

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

这可能是这样的:

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

Format.printf "%a" (pp_result Format.pp_print_string) (Success "hello")

pp_result子句生成deriving的位置。请注意,pp_result将格式化函数作为参数,用于打印任何'a

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