Inductive Datatype: Convert an expression into a string

Hi, I acknowledged that we have a tutorial in this conversion but I have a new type and I keep getting an error message for this conversion of the new type.

let rec expr_to_str (e:expr) : string = match e with
 | Add (left, right) ->
   "Add" ^ " ("  ^ serialize left ^ ", " ^ serialize right ^ ")"
 | Mul (left, right) ->
   "Mul" ^ " (" ^ serialize left ^ "," ^ serialize right ^ ")"
 | Val v -> "Val" ^ " (" ^ v ^ ")"
 | If (expr1,expr2,expr3) ->
  "If" ^  " (" ^ serialize expr1 ^ ", " ^ serialize expr2  ^ ", " ^ serialize expr3 ^ ")"

I have an error message on the “Val v” conversion:

   Val v -> "Val" ^ " (" ^ v ^ ")"
Error: This expression has type value but an expression was expected of type string

Do I need another pattern matching on v? Since type value has Int, Bool and Closure.
Thank you!

Yes, you will need to use pattern matching to convert your value type to a string.

You can add a function like this:

let string_of_value = function
  | Bool true -> "true"
  | Bool false -> "false"
  | Int i -> string_of_int i
  ...

Then just change that line to:

 | Val v -> "Val" ^ " (" ^ string_of_value v ^ ")"

Hope that helps!

1 Like

@zshipko
I have another question. How can I convert

(Lambda ("n", Add (Id "n", Val (Int 1))))

to

"Lambda (\"n\", Add (Id \"n\", Val (Int 1)))"?

My output looks like this:

- : string = "Lambda  (n, Add (Id n, Val (Int 1)))"

What I am missing is instead of having n, I should have:

\"n\"

How can I achieve this result?
Thank you!

Are you escaping the quotation marks and backslash?

As an example (since you didn’t post your code for this), instead of:

"Lambda (" ^ x ^ ", " ^  expr_to_string y ^ ")"

You should use something like

"Lambda (\\\"" ^ x ^ "\\\", " ^  expr_to_string y ^ ")"

This can also be accomplished using Printf.sprintf:

Printf.sprintf "Lambda (\\\"%s\\\", %s)" x y
1 Like

For this kind of expressions I think the alternative string syntax helps a lot as you can avoid the escapings:

Printf.sprintf {|Lambda (\"%s\", %s)|} x y

And in this case I think it would be enough to do

Printf.sprintf {|Lambda (“%s", %s)|} x y

The escape in thos strings should be displayed by ocaml because you have already the quotes around the string. But I have not tested it

1 Like

Also note that there is a %S formatter (uppercase S) that will display a string in OCaml syntax, that is with surrounding double quotes and escaped special characters (such as double quotes).

2 Likes

Beware! %S not only put quotes around the string, but also outputs codepoint for non-ascii chars:

# Format.printf "%S" "ééç" ;;
"\195\169\195\169\195\167"- : unit = ()

You should not use it if you only want quotes.

2 Likes