ocaml - 如何在 Ocaml 中将非内置类型转换为字符串?

标签 ocaml

我正在尝试编写一个模块,将 x:int = if true then 3 else 5 转换为字符串

这是我到目前为止的代码

module Ast =
struct

type typ = Bool | Int
type var = A | B | C | D | E | F
type exp = Const of int * typ
           | App of string * exp list
           | If of exp * exp * exp
           | And of exp * exp
           | Or of exp * exp
       | Id of var * typ * exp


let rec toString (t) =
    let formatDec1(va,ty,e) = ???
    match t with
    Const(n, _) -> print_int n
      | App(id, [e1; e2]) -> formatter(" " ^ id ^ " ", e1, e2)
      | App(id, [e1]) -> formatter(" " ^ id ^ " ", e1, Const(0, Int))
      | App(id, _) -> formatter(" " ^ id ^ " ", Const(0, Int), Const(0, Int))
      | If(e1, e2, e3) -> formatIf(e1, e2, e3)
      | And(e1, e2) -> formatter(" && ", e1, e2)
      | Or(e1, e2) -> formatter(" || ", e1, e2)
      | Id(va,ty,e) -> formatDecl(va,ty,e)
end

我仍然是 OCaml 的初学者,找不到任何关于在线转换为字符串的信息。谢谢!

最佳答案

您想使用 ml 语法漂亮地打印符号表达式。有一些库可以处理所谓的 sexp,但我从未使用过它们,我无法评论它们的用途,而且它可能不是你想要的,因为它会回避练习的目的。

我认为您与已有的内容有些接近,但是您的代码中存在一些语法错误。我会给你一堆建议来帮助你缩小差距。

首先,关于 OCaml 语法:

回想一下,您不需要为函数参数使用括号。函数定义的一般语法是:

let fun_name arg1 arg2 arg3 = function_body

如果你写
let fun_name (arg1,arg2,arg3) = ...

您实际上是在定义一个带有 1 个参数的函数,它本身就是 3 个值的元组。

在表达式中,您可以使用 let ... in 定义局部值。构造,就像定义顶级值时一样(就像我在上面所做的那样)。如果这些值定义不是相互依赖的,您可以使用 and几个值定义之间的关键字。

例如,
let x = 1 
and y = "a" in
...

将定义 2 个值 xy可以在后续代码中使用。

在您的代码中

您拥有的类型提供了一些符号表达式语言,您可以使用它定义表达式,例如您在示例中给出的表达式:

"x:int = if true then 3 else 5"将是:
Id("x", 
   Int, 
   (If (Const (1, Bool), 
        Const (3, Int), 
        Const (5, Int))))

实际上,您需要递归地遍历该值,并将返回的字符串组合成一个更大的字符串。或者,您可以使用字符串列表,并在最后进行字符串连接。
查看该示例,您可能会看到它是如何工作的:
"x" ^ (":" ^ "int") ^ "=" ^ ("if" ^ ("true") ^ "then" ^ ("3") ^ ("5"))

您可以在上面看到不同的子表达式模式。我用括号来表示它们。

在您的 toString 函数中,有 3 个未定义的值:
  • formatter (采用 string * exp * exp 类型的三元组的函数)
  • formatDec1 (另一个函数采用 exp * exp * exp 类型的三元组)
  • formatIf (与 formatDec1 相同)

  • 您使用了关键字 rec在您的 toString函数定义,表示函数是递归的。在我看来,你不需要上面的 3 个函数(它们是你最初分配的一部分,还是你自己定义的?),而只需要 toString函数和字符串连接在那里。
    App你的 ARM exp类型非常通用:您可以定义任意数量的参数的应用,因此您的字符串转换代码应该考虑到这种可能性。您可以使用一些列表函数(想到 fold_left)来处理它。

    关于ocaml - 如何在 Ocaml 中将非内置类型转换为字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13350459/

    相关文章:

    ocaml - 参数为无符号 32 位整数的函数

    parsing - 在用 Ocaml 编写的编译器中,在哪里/如何声明变量的唯一键?

    module - Ocaml 仿函数、模块和子模块

    html - 在 OCaml 网络爬虫中跟踪 HTTP 重定向

    algorithm - 将数字添加到函数 OCaml 中的列表

    ocaml - ML 系列编译器是否对尾调用进行了任何复杂的优化?

    ocaml - 如何进行伽罗华域乘法?

    algorithm - 内联算法

    polymorphism - 在函数签名中包含模块签名和该模块类型的值

    functional-programming - 如何将移位/重置转换为delimcc?