我当前正在尝试编写OCaml函数,该函数将计算表达式并返回布尔值。我已经尝试过进行在线研究,而我能找到的最接近答案是this one。但是,我仍然遇到麻烦,这使我不得不问自己一个问题。
这是基本代码:
type equation =
| True
| False
| Equal of exp * exp
and exp =
| Val of int
| Add of exp * exp
| Sub of exp * exp
let rec eval : equation -> bool
= fun f ->
match f with
| True -> true
| False -> false
| Equal (x, y) -> match (x, y) with
| (Val a, Val b) -> if (x = y) then true else false
| ((Add (Val a, Val b), c) -> eval (Equal (Val (a + b), c))
程序不完整,最后一行中对eval
的递归调用是我遇到的问题。我想到的一个具体的输入示例是:
eval (Equal (Add (Add (Val 1, Val 2), Val 3), Val 6))
这应该计算为true
,因为两个Add
的总和为6,并且Equal
将Val 6
与Val 6
进行比较。我遇到的麻烦是如何递归调用该函数以计算表达式中的第二个Add
,以便Add (Val 2, Val 2)
首先计算为Val 3
,然后是第一个{{1} }将Add
与Val 3
相加。我现在编写的程序仅评估两个Val 3
之一。
有什么我应该考虑或牢记的吗?欢迎任何反馈。谢谢。
答案 0 :(得分:1)
正如@Amadan所提到的,定义一个首先将表达式计算为int eval_exp: exp -> int
的函数更容易。然后,您可以只对元组Equal(e1, e2)
中的两个表达式求值并进行比较(eval: equation -> bool
)。
您也不需要类型equation
中的True和False值,因为您可以从函数返回bool而不进行模式匹配。请注意,如果由于某种原因再次将它们传递给eval
函数,则可能需要True和False。
type equation =
Equal of exp * exp
and exp =
| Val of int
| Add of exp * exp
| Sub of exp * exp
let rec eval (e: equation) : bool =
let rec eval_exp e =
match e with
| Val i -> i
| Add (e1, e2) -> (eval_exp e1) + (eval_exp e2)
| Sub (e1, e2) -> (eval_exp e1) - (eval_exp e2)
in
match e with
| Equal (e1, e2) ->
if (eval_exp e1) = (eval_exp e2)
then true
else false