OCaml:如何安装漂亮的打印机并在代码中使用它?
在OCaml的顶级和调试器中,可以注册一台漂亮的打印机 通过OCaml:如何安装漂亮的打印机并在代码中使用它?,ocaml,pretty-print,Ocaml,Pretty Print,在OCaml的顶级和调试器中,可以注册一台漂亮的打印机 通过安装打印机名称。 除了OCaml代码之外,有没有其他方法可以实现同样的效果? 更具体地说,我需要一个不需要 为每次调用log显式指定漂亮的打印机。 也就是说,类似于: (* First, user sets a global pretty-printer for a type *) let pp_foo : Foo -> string = ... let () = Logging.register pp_foo ... (* T
安装打印机名称
。
除了OCaml代码之外,有没有其他方法可以实现同样的效果?
更具体地说,我需要一个不需要
为每次调用log
显式指定漂亮的打印机。
也就是说,类似于:
(* First, user sets a global pretty-printer for a type *)
let pp_foo : Foo -> string = ...
let () = Logging.register pp_foo
...
(* Then it can be used like that *)
let foo : Foo = ...
let () = Logging.log foo
这是不可能的,原因有二: 首先,OCaml在运行时擦除类型。因此,无法区分具有相同内存表示的值。例如,
[]
、0
或None
在编译后具有相同的表示
其次,log
函数的类型是'a'a->unit
。换句话说,该规范规定,您的函数日志应该适用于过去、现在和将来的任何类型。仅当函数忽略其参数时,才可能出现这种情况,例如:
let f _x = g ()
换句话说,真正的问题可能是你的问题是什么
let () = Logging.log pp_foo foo
?由于两个原因,这是不可能的: 首先,OCaml在运行时擦除类型。因此,无法区分具有相同内存表示的值。例如,
[]
、0
或None
在编译后具有相同的表示
其次,log
函数的类型是'a'a->unit
。换句话说,该规范规定,您的函数日志应该适用于过去、现在和将来的任何类型。仅当函数忽略其参数时,才可能出现这种情况,例如:
let f _x = g ()
换句话说,真正的问题可能是你的问题是什么
let () = Logging.log pp_foo foo
与Octachron所说的不矛盾,但实际上有可能获得一些倾倒设施,这将是多态的。它将是脆弱的,实际上不会区分
[]
、0
、None
,但在OCaml内置类型中工作得很好。例如,可以在不同修改的库中找到此函数,并且库在dump
名称下提供了一个函数,下面是与它进行顶级交互的示例:
# #use "topfind";;
# #require "extlib";;
# Std.dump;;
- : 'a -> string = <fun>
# Std.dump ["hello"; "world"];;
- : string = "[\"hello\"; \"world\"]"
# Std.dump [];;
- : string = "0"
# Std.dump None;;
- : string = "0"
# Std.dump [|"hello"|];;
- : string = "(\"hello\")"
# module Abstract : sig type t val x : t end =
struct type t = string list let x = ["hello, world"] end;;
module Abstract : sig type t val x : t end
# Std.dump Abstract.x;;
- : string = "[\"hello, world\"]"
#
##使用“topfind”;;
##需要“extlib”;;
#标准垃圾场;;
-:'a->string=
#Std.dump[“你好”;“世界”];;
-:string=“[\“你好”;\“世界\]”
#标准转储[];;
-:string=“0”
#标准无;;
-:string=“0”
#Std.dump[|“你好”|];;
-:string=“(\“hello\”)”
#模块摘要:sig类型t val x:t end=
struct type t=string list让x=[“hello,world”]end;;
模块摘要:sig类型t val x:t end
#标准dump Abstract.x;;
-:string=“[\”你好,世界\]”
#
有了这些能力,我仍然建议您仅将其用于调试目的
最后,如果你想知道顶级漂亮的打印是如何工作的,下面是答案。事实上,它依赖于类型化环境,该环境可用于顶级,部分是解释器,部分是编译器。这个漂亮的印刷设备仍然相当脆弱 这与Octachron的说法并不矛盾,但实际上有可能获得一些倾倒设施,这将是多态的。它将是脆弱的,实际上不会区分
[]
、0
、None
,但在OCaml内置类型中工作得很好。例如,可以在不同修改的库中找到此函数,并且库在dump
名称下提供了一个函数,下面是与它进行顶级交互的示例:
# #use "topfind";;
# #require "extlib";;
# Std.dump;;
- : 'a -> string = <fun>
# Std.dump ["hello"; "world"];;
- : string = "[\"hello\"; \"world\"]"
# Std.dump [];;
- : string = "0"
# Std.dump None;;
- : string = "0"
# Std.dump [|"hello"|];;
- : string = "(\"hello\")"
# module Abstract : sig type t val x : t end =
struct type t = string list let x = ["hello, world"] end;;
module Abstract : sig type t val x : t end
# Std.dump Abstract.x;;
- : string = "[\"hello, world\"]"
#
##使用“topfind”;;
##需要“extlib”;;
#标准垃圾场;;
-:'a->string=
#Std.dump[“你好”;“世界”];;
-:string=“[\“你好”;\“世界\]”
#标准转储[];;
-:string=“0”
#标准无;;
-:string=“0”
#Std.dump[|“你好”|];;
-:string=“(\“hello\”)”
#模块摘要:sig类型t val x:t end=
struct type t=string list让x=[“hello,world”]end;;
模块摘要:sig类型t val x:t end
#标准dump Abstract.x;;
-:string=“[\”你好,世界\]”
#
有了这些能力,我仍然建议您仅将其用于调试目的
最后,如果你想知道顶级漂亮的打印是如何工作的,下面是答案。事实上,它依赖于类型化环境,该环境可用于顶级,部分是解释器,部分是编译器。这个漂亮的印刷设备仍然相当脆弱