【问题标题】:How to print an abstract data type within in a functor in ocamldebug如何在 ocamldebug 的仿函数中打印抽象数据类型
【发布时间】:2015-12-09 01:48:41
【问题描述】:

我正在为如何为仿函数内使用的类型安装打印机功能而苦苦挣扎。结构有点像这样:

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_printerinstall_printer Input.printInput.t 成功安装打印机,但是从F (Input) 内部打印时,它无法识别出正确的类型。

根据要求,这里是一个独立的示例。应该在打开调试的情况下构建它,然后在调试器中使用load_printer 加载.cmo

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,仅供参考。
  • 如果您提供实际编译的代码,这将有助于我集中注意力。我不想花太多时间思考与您所问的问题不同的问题 :-) 另一方面,如果上次没有人回答,很可能没有好的答案。
  • @EdgarAroutiounian 您可以在 OCaml 顶层安装打印机(不仅仅是 ocamldebug)。我发现它在过去很有用;有时有一个大值的简单表示法。
  • @JeffreyScofield 我更新了问题(不知道这是否会自动向评论者发送通知)

标签: debugging ocaml pretty-print


【解决方案1】:

在我看来,没有办法做你想做的事。一种看待这种情况的方法是 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 选择打印机的方式来获取值。但这听起来也有点毛骨悚然。

(抱歉,我帮不上忙,但正如我所说,这表明这个问题被问到但从未得到回答。)

【讨论】:

  • hm,如果这真的不可能,它似乎限制了 ocamldebug 的用处。我希望调试器实际上可以显示正在运行的程序中的值。也许这就是人们不再使用它的原因之一?我在哪里可以提交功能请求?
  • 我认为你对 ocamldebug 的流行程度是正确的。您可以在caml.inria.fr/mantis 提交 OCaml 的功能请求@ 至少已经有一个请求让 ocamldebug 查看抽象类型。这是看待问题的一种方式。
【解决方案2】:

这不是解决方案。这是一种解决方法的开始,它至少允许为函子输出中的类型加载打印机。但是,加载的打印机实际上无法在 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安装打印功能。这成功加载了具有正确类型的函数;但是正确性没有得到认可,因此打印仍然失败。

【讨论】:

    猜你喜欢
    • 2019-03-12
    • 1970-01-01
    • 2019-07-06
    • 1970-01-01
    • 1970-01-01
    • 2016-03-10
    • 2017-01-06
    • 2019-05-02
    • 2012-01-16
    相关资源
    最近更新 更多