如何在 ocamldebug 的仿函数中打印抽象数据类型
How to print an abstract data type within in a functor in ocamldebug
我正在努力解决如何为仿函数内部使用的类型安装打印机函数的问题。结构看起来有点像这样:
module Input : sig
type t
val print fmt arg : Format.formatter -> t -> unit
end
module type INPUT = module type of Input
module F (I:INPUT) : sig
val foo : I.t -> unit
end
现在我想打印 F.foo
中使用的类型 Input.t
的值。我可以使用 load_printer
和 install_printer Input.print
为 Input.t
成功安装打印机,但是当从 F (Input)
.[=25= 内部打印时它无法识别类型是否正确]
这里要求的是一个独立的例子。它应该在打开调试的情况下构建,然后 .cmo
应该在调试器中使用 load_printer
加载。
module type INPUT = sig
type t
val print : Format.formatter -> t -> unit
val to_list : t -> int list
val of_list : int list -> t
end
module V1 : INPUT = struct
type t = int
let print fmt i = Format.fprintf fmt "%d" i
let to_list i = [i]
let of_list = function [i] -> i | _ -> raise @@ Failure ""
end
module V2 : INPUT = struct
type t = int * int
let print fmt (i, j) = Format.fprintf fmt "%d, %d" i j
let to_list (i, j) = [i; j]
let of_list = function [i; j] -> (i, j) | _ -> raise @@ Failure ""
end
module F (V:INPUT) = struct
let ssquare v = (V.to_list v)
|> List.map (fun i -> i * i)
|> List.fold_left (+) 0
let print fmt v =
let open Format in
print_string "<";
V.to_list v |> List.iter print_int;
print_string ">"
end
module F2 = F (V2);;
let v2 = V2.of_list [2;4] in
let _ = Format.fprintf Format.std_formatter "%a\n" F2.print v2 in
let _ = F2.ssquare v2 in
()
这个程序打印值 v2
就好了。但是调试的时候其实有两个问题。我可以 install_printer V2.print
,但是当将调试器放在 ssquare
函数中并调用 print v2
时,这不会打印它。此外,我什至不知道如何安装仿函数中定义的 print
。
在我看来,没有办法做你想做的事。一种看待这个问题的方法是 ocamldebug 通过 type 匹配打印函数。但是 ocamldebug 认为你要打印的值 v
的类型是 V.t
,而 V 是仿函数 F
的形式参数。没有办法(我能想到)制作一个接受这种类型的函数。函数 F.print
似乎是一个候选函数,但在您实例化仿函数之前它不是一个实际函数。并且实例化的仿函数中print函数接受的类型不再是V.t
.
例如,ocamldebug 认为 F2.print
接受的类型是 V2.t
:
(ocd) print N.F2.print
N.F2.print: 'a -> N.V2.t -> unit = <fun>
如果有方法可以做这样的事情,那就太好了,可能是通过丰富 ocamldebug 选择打印机作为值的方式。但听起来也有点毛骨悚然。
(抱歉,我帮不上什么忙,但正如我所说,这表明有人问了这个问题,但从未回答过。)
这不是解决方案。这是解决方法的开始,它至少允许加载仿函数输出中类型的打印机。但是,加载的打印机实际上无法打印 ocamldebug 中的任何内容。我认为这是因为 ocamldebug 无法识别打印机函数类型与打印机类型之间的相等性。不管怎样,就这样吧。
创建一个新文件debug_printers.ml
,其中执行与相关模块中相同的函子应用程序。假设上面问题中列出的独立文件名为 vsource.ml
。那么debug_printers
应该包含
open Vsource
module F2 = F (V2)
let print_f2 = F2.print
然后将其编译为debug_printers.d.cmo
并通过load_printer "debug_printers.d.cmo"
将其加载到ocamldebug
中。最后通过install_printer print_f2
安装打印功能。这成功加载了具有正确类型的函数;然而正确性没有得到认可,所以打印仍然失败。
我正在努力解决如何为仿函数内部使用的类型安装打印机函数的问题。结构看起来有点像这样:
module Input : sig
type t
val print fmt arg : Format.formatter -> t -> unit
end
module type INPUT = module type of Input
module F (I:INPUT) : sig
val foo : I.t -> unit
end
现在我想打印 F.foo
中使用的类型 Input.t
的值。我可以使用 load_printer
和 install_printer Input.print
为 Input.t
成功安装打印机,但是当从 F (Input)
.[=25= 内部打印时它无法识别类型是否正确]
这里要求的是一个独立的例子。它应该在打开调试的情况下构建,然后 .cmo
应该在调试器中使用 load_printer
加载。
module type INPUT = sig
type t
val print : Format.formatter -> t -> unit
val to_list : t -> int list
val of_list : int list -> t
end
module V1 : INPUT = struct
type t = int
let print fmt i = Format.fprintf fmt "%d" i
let to_list i = [i]
let of_list = function [i] -> i | _ -> raise @@ Failure ""
end
module V2 : INPUT = struct
type t = int * int
let print fmt (i, j) = Format.fprintf fmt "%d, %d" i j
let to_list (i, j) = [i; j]
let of_list = function [i; j] -> (i, j) | _ -> raise @@ Failure ""
end
module F (V:INPUT) = struct
let ssquare v = (V.to_list v)
|> List.map (fun i -> i * i)
|> List.fold_left (+) 0
let print fmt v =
let open Format in
print_string "<";
V.to_list v |> List.iter print_int;
print_string ">"
end
module F2 = F (V2);;
let v2 = V2.of_list [2;4] in
let _ = Format.fprintf Format.std_formatter "%a\n" F2.print v2 in
let _ = F2.ssquare v2 in
()
这个程序打印值 v2
就好了。但是调试的时候其实有两个问题。我可以 install_printer V2.print
,但是当将调试器放在 ssquare
函数中并调用 print v2
时,这不会打印它。此外,我什至不知道如何安装仿函数中定义的 print
。
在我看来,没有办法做你想做的事。一种看待这个问题的方法是 ocamldebug 通过 type 匹配打印函数。但是 ocamldebug 认为你要打印的值 v
的类型是 V.t
,而 V 是仿函数 F
的形式参数。没有办法(我能想到)制作一个接受这种类型的函数。函数 F.print
似乎是一个候选函数,但在您实例化仿函数之前它不是一个实际函数。并且实例化的仿函数中print函数接受的类型不再是V.t
.
例如,ocamldebug 认为 F2.print
接受的类型是 V2.t
:
(ocd) print N.F2.print
N.F2.print: 'a -> N.V2.t -> unit = <fun>
如果有方法可以做这样的事情,那就太好了,可能是通过丰富 ocamldebug 选择打印机作为值的方式。但听起来也有点毛骨悚然。
(抱歉,我帮不上什么忙,但正如我所说,这表明有人问了这个问题,但从未回答过。)
这不是解决方案。这是解决方法的开始,它至少允许加载仿函数输出中类型的打印机。但是,加载的打印机实际上无法打印 ocamldebug 中的任何内容。我认为这是因为 ocamldebug 无法识别打印机函数类型与打印机类型之间的相等性。不管怎样,就这样吧。
创建一个新文件debug_printers.ml
,其中执行与相关模块中相同的函子应用程序。假设上面问题中列出的独立文件名为 vsource.ml
。那么debug_printers
应该包含
open Vsource
module F2 = F (V2)
let print_f2 = F2.print
然后将其编译为debug_printers.d.cmo
并通过load_printer "debug_printers.d.cmo"
将其加载到ocamldebug
中。最后通过install_printer print_f2
安装打印功能。这成功加载了具有正确类型的函数;然而正确性没有得到认可,所以打印仍然失败。