我正在Ocaml中编写一个小编译器。在ast.mli
中,我定义了两种表达式
type int_expr =
| Integer_constant of int
| Evar of string
| Ebinop of binop * int_expr * int_expr
| Ecell of int_expr * int_expr (* Sheet[ , ] *)
type bool_expr =
| Bool_constant of bool
| Bcmp of cmp * int_expr * int_expr
| Band of bool_expr * bool_expr
| Bor of bool_expr * bool_expr
| Bnot of bool_expr
在interp.ml
中,我想定义一个名为eval_expression
的函数来计算任何可能是int_expr或bool_expr的表达式
let rec eval_expression env = function
| Integer_constant n -> Integer n
| Ebinop (op, n, m) -> ...
| Evar x -> ...
| Ecell (r, c) -> ...
| Bool_constant b -> ...
| Bnot c -> ...
| Bor (c1, c2) -> ...
| Band (c1, c2) -> ...
但是在编译时会返回错误:
ocamlc -c interp.ml
File "interp.ml", line 63, characters 4-19:
Error: This pattern matches values of type Ast.bool_expr
but a pattern was expected which matches values of type Ast.int_expr
make: *** [interp.cmo] Error 2
有人能告诉我如何更改表达式类型的结构以便eval_expression
有效吗?非常感谢你!
答案 0 :(得分:4)
您需要为任意类型的表达式编写另一种类型:
type expr = Iexpr of int_expr
| Bexpr of bool_expr
和最终值的类型,可以是整数或布尔值
type value = Ivalue of int
| Bvalue of bool
并编写一个函数evaluate : expr -> value
。
对于它的价值,我从未觉得以这种方式将允许的表达式静态分离为int-typed和bool-typed表达式在ML类语言中确实值得。一旦向对象语言添加更丰富的类型,最终会出现大量重复语法。你真正想要的是将对象语言类型踢入你的实现语言的类型层,但最终在ML中变得非常难看。它在Haskell更丰富的类型和类型的机器中更好一点,但它仍然感觉像一个非常受影响的编程风格。
最后,对于小小的一次性解释器,我通常只为我的对象语言的类型和表达式编写单独的tp
和expr
类型,并将eval写为expr -> tp -> value