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

otc*_*com 2 ocaml

我正在尝试编写一个模块来转换类似x:int = if true,然后将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
Run Code Online (Sandbox Code Playgroud)

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

did*_*erc 5

你想用ml语法打印符号表达式.有些图书馆可以处理所谓的sexp,但是我从来没有使用它们,我不能评论它们的用途,它可能不是你想要的,因为它会回避练习的目的.

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

首先,关于OCaml语法:

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

let fun_name arg1 arg2 arg3 = function_body
Run Code Online (Sandbox Code Playgroud)

如果你写

let fun_name (arg1,arg2,arg3) = ...
Run Code Online (Sandbox Code Playgroud)

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

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

例如,

let x = 1 
and y = "a" in
...
Run Code Online (Sandbox Code Playgroud)

将定义2个值x,y并且可以在后续代码中使用.

在你的代码中

你给出的类型有一个小的符号表达式语言,你可以使用它来定义表达式,例如你给出的表达式:

"x:int = if true,然后3 else 5"将是:

Id("x", 
   Int, 
   (If (Const (1, Bool), 
        Const (3, Int), 
        Const (5, Int))))
Run Code Online (Sandbox Code Playgroud)

实际上,您需要递归地遍历该值,并将返回的字符串组合成更大的字符串.或者,您可以使用字符串列表,并在结尾处执行字符串连接.看一下这个例子,你可能会看到它是如何工作的:

"x" ^ (":" ^ "int") ^ "=" ^ ("if" ^ ("true") ^ "then" ^ ("3") ^ ("5"))
Run Code Online (Sandbox Code Playgroud)

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

在toString函数中,有3个未定义的值:

  • formatter(采用3元组类型的函数string * exp * exp)
  • formatDec1(另一个采用3元组类型的函数exp * exp * exp)
  • formatIf(同formatDec1)

rectoString函数定义中使用了关键字,表示该函数是递归的.在我看来,你不需要上面的3个函数(它们是你初始赋值的一部分,还是你自己定义它们?),但只是toString函数和字符串连接.

App你的exp类型的臂很通用:你可以定义任意数量的参数的应用程序,所以你的字符串转换代码应该考虑到这种可能性.您可以使用一些列表功能(fold_left想到)来处理它.