【问题标题】:Printing variant types in OCaml在 OCaml 中打印变体类型
【发布时间】:2015-02-15 15:10:59
【问题描述】:

在我的 OCaml 程序中,我花费大量时间一遍又一遍地为变体类型编写“to_string”。我需要它们来进行调试,或者因为我需要特定的格式化输出。

到目前为止,他们遵循如下模板:

let rec to_string = function                                                                                                               
    | Var x -> x                                                                 
    | Implies (f1, f2) -> Printf.sprintf "(=> %s %s)" (to_string f) (to_string f2)
    | And (f1, f2) -> Printf.sprintf "(& %s %s)" (to_string f1) (to_string f2)   
    | Or (f1, f2) -> Printf.sprintf "(| %s %s)" (to_string f1) (to_string f2)    
    | Not (f) -> Printf.sprintf "(~ %s)" (to_string f)                           
    | True -> "#t"                                                               
    | False ->"#f"        

我想知道是否有比这更方便/传统的方法,可能是语言的最新发展。例如,根据类型自动生成模板?可用于调试的通用打印函数?

“Real World OCaml”中提倡的一种方法是使用 Core 库的 Sexp 模块,该模块为此目的提供了便利。如果您不需要对如何打印值进行太多自定义,它似乎工作得很好。我想知道是否有其他/更好的选择。

【问题讨论】:

  • 有一个 camlp4 预处理器,它使用新指令 deriving 扩展了 ocaml 语法,除其他外,您可以指示是否希望为您机械地编写字符串转换函数。让人想起 Haskell 的派生 (deriving show) 的语法。
  • 图书馆是there。虽然我从未使用过它,但我知道它非常好。我不确定它是否仍可用于 4.0+ 版本的 Ocaml。 (其中之一)作者有一个关于camlp4的优秀教程,one chapter描述了如何开发这样的扩展。
  • 哦,可能和Core里面发现的一样,不知道。
  • 谢谢。它似乎与 Core 中所做的类似。基本上,您可以在类型定义之后添加“with sexp”,camlp4 会为您派生与​​ Sexp.t 之间的转换函数(有通用打印和解析函数)。
  • 啊,对了,我现在想起来了:iirc Sexp 的目标是为 ocaml 提供符号表达式(我相信在 lisp 中),它们可以以人类可读的格式序列化。一个副作用是它可以方便地转换为字符串。

标签: printing ocaml variant


【解决方案1】:

很少有你可能会觉得有趣的基于类型的生成器,比如derivingtyperepsexplib 等。但我不希望有一些神奇的东西会读懂你的想法在编译时,根据你的口味和感受编写一个漂亮的打印函数。关于模板,那么所有的模板引擎都是某种模式匹配(通常是字符串类型),而 OCaml 已经为您提供了开箱即用的模式匹配。并且不要忘记,您的类型定义是递归的,这使得基于模板的方法更难使用。您可以使用一些基于jsonxml 的自动转储程序,例如ocaml-cow 并实现某种xslt 转换,但最终会得到大量代码,这些代码实际上是在重新发明OCaml 的本机模式匹配。

因此,对于像您这样的小型语言,编写此 to_string 函数是最好的解决方案。我认为这是向计算机表达你的想法的最自然的方式。我还建议使用Format 模块,并使用%a 说明符进行递归。此外,Format 模块具有tags 的概念。标签允许在格式字符串中按字面意思标记文本片段, 标记的格式可以用下面的例子来解释:

@{<html>@{<head>@{<title>Tags!@}@}@{<body>Hello!@}@}

这可以自动转成HTML:

  <html>
   <head>
    <title>
    Tags!
    </title>
   </head>
   <body>
   Hello!
   </body>
  </html>

您也可以将其转移到LaTeXjson 或其他任何东西,包括什么都没有(即完全忽略标签)。但是标签更多的是关于处理格式和元信息,比如语法高亮和引用。它们实际上不能影响具体的语法。

对于丰富的语法树,编写递归的漂亮打印函数集的方法不能很好地扩展。这就是 OCaml 中有 O 的原因。您可以使用开放递归来实现带有大量钩子(即方法)的 AST 访问者类。这是OCaml 本身和camlp4 中使用的方法。

【讨论】:

    猜你喜欢
    • 2011-06-14
    • 2020-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多