在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#中的那个?
答案 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#中的自动打印功能。无论如何,不清楚反射在抽象类型的语言中是否能够很好地发挥作用。