すでに解決済みかもしれませんが、同じような方がいるかもしれないので回答します。
function
について
OCamlのfunction
キーワードはlet f x = match x with ...
のショートハンドです。
そのため、let rec string_of_exp v = function ...
の引数v
は不要です。
ご参考までに、以下のf
とg
は同じです。
ocaml
1let f x =
2 match x with
3 | None -> "None"
4 | Some v -> v
5let g = function
6 | None -> "None"
7 | Some v -> v
string_of_exp
を書く
以上の話を踏まえ、関数string_of_exp
の型を考えます。
欲しい関数はデータ型exp
をstring
に変換する関数ですから、以下のような型の関数になります。
ocaml
1val string_of_exp : exp -> string
では、各パターンマッチでstring
を返すように関数を書いていきましょう。
ocaml
1let rec string_of_exp = function
2 | Num n -> (* n: int を string に変換する式 *)
3 | Var v -> (* v: string を string に変換する式 *)
4 | Add (x, y) -> (* x: exp, y: exp を string に変換する式 *)
5 | Mul (x, y) -> (* x: exp, y: exp を string に変換する式 *)
引数がNum
のときはstring_of_int
でstringに変換します。
ocaml
1let rec string_of_exp = function
2 | Num n -> string_of_int n
引数がVar
のときは値がstring
ということでおそらく変数名でしょうから、そのまま返します。
ocaml
1let rec string_of_exp = function
2 | Var v -> v
引数がAdd
のときは(値 + 値)
と表示するか足し算した結果を表示するかによりますが、今回は「exp 型の数式の文字列表現」ということなので、前者とします。
ocaml
1let rec string_of_exp = function
2 | Add (x, y) -> Printf.sprintf "(%s + %s)" (string_of_exp x) (string_of_exp y)
引数がMul
のときもAdd
と同様に(値 * 値)
と表示することにします。
ocaml
1let rec string_of_exp = function
2 | Mul (x, y) -> Printf.sprintf "(%s * %s)" (string_of_exp x) (string_of_exp y)
以上をまとめて、string_of_exp
は以下のようになります。
ocaml
1let rec string_of_exp = function
2 | Num n -> string_of_int n
3 | Var v -> v
4 | Add (x, y) -> Printf.sprintf "(%s + %s)" (string_of_exp x) (string_of_exp y)
5 | Mul (x, y) -> Printf.sprintf "(%s * %s)" (string_of_exp x) (string_of_exp y)
参考情報
以下にpuroさんが書かれたコードにでてくるいくつかの式の型を書いておきます。
int_of_exp
やmake_sum
がどういった関数なのか不明だったので、一部は関数名から想像した型を前提に書いています。
ocaml
1string_of_int n (* string *)
2int_of_exp x (* int_of_exp: exp -> int なら int *)
3(x+y) (* x: exp, y: exp なので対応する + が定義されておらず、型エラー *)
4make_sum (...) (* make_sum: int list -> int なら int *)
注意点
わかりやすさを優先し、以上のstring_of_exp
は末尾再帰になっていません。
大きな式を文字列に変換しようとするとスタックオーバーフローする可能性があるので、そのときは何回かに分けて呼び出すか、関数を末尾再帰に書き直してください。
以上、お役に立てれば幸いです。