recursion - OCaml 递归函数

标签 recursion functional-programming eval ocaml reduce

我是 OCaml 的新手。我写了这段代码来减少代数表达式:

type expr =
    | Int of int
    | Float of float
    | Add of expr*expr
    | Sub of expr*expr
    | Mult of expr*expr
    | Div of expr*expr
    | Minus of expr

let rec eval expression = match expression with
    | Add (e1, e2) -> (eval e1) +. (eval e2)
    | Sub (e1,e2) -> (eval e1) -. (eval e2)
    | Mult (e1,e2) -> (eval e1) *. (eval e2)
    | Div (e1, e2) -> (eval e1) /. (eval e2)
    | Minus (e1) -> -.(eval e1)
    | Int i -> (float) i
    | Float f -> f

let rec simplify_expr e = match e with
| Add (e1,e2) -> if (eval e1) == 0.0 then simplify_expr e2 
                                    else if (eval e2) == 0.0 then simplify_expr e1 
                                    else Add (simplify_expr e1, simplify_expr e2)
| Mult(e1,e2) -> if (eval e1) == 1.0 then simplify_expr e2 
                                    else if (eval e2) == 1.0 then simplify_expr e1 
                                    else Mult (simplify_expr e1, simplify_expr e2)
| Sub (e1, e2) -> if (eval e1) == 0.0 then simplify_expr e2 
                                    else if (eval e2) == 0.0 then simplify_expr e1 
                                    else Sub (simplify_expr e1, simplify_expr e2)
| Div (e1, e2) -> if (eval e1) == 1.0 then simplify_expr e2 
                                    else if (eval e2) == 1.0 then simplify_expr e1 
                                    else Div (simplify_expr e1, simplify_expr e2)
| Int i -> e
| Minus e1 -> simplify_expr(e1)
| Float f -> e

我这样调用 simplify_expr:

Expr.simplify_expr Expr.Mult (Expr.Int 4, Expr.Add (Expr.Int 1, Expr.Int 0));;

我的答案是错误的:

- : Expr.expr = Expr.Mult (Expr.Int 4, Expr.Add (Expr.Int 1, Expr.Int 0))

下面我粘贴调用的堆栈。

Expr.simplify_expr <--
  Expr.Mult (Expr.Int 4, Expr.Add (Expr.Int 1, Expr.Int 0))
Expr.eval <-- Expr.Int 4
Expr.eval --> 4.
Expr.eval <-- Expr.Add (Expr.Int 1, Expr.Int 0)
Expr.eval <-- Expr.Int 0
Expr.eval --> 0.
Expr.eval <-- Expr.Int 1
Expr.eval --> 1.
Expr.eval --> 1.
Expr.simplify_expr <-- Expr.Add (Expr.Int 1, Expr.Int 0)
Expr.eval <-- Expr.Int 1
Expr.eval --> 1.
Expr.eval <-- Expr.Int 0
Expr.eval --> 0.
Expr.simplify_expr <-- Expr.Int 0
Expr.simplify_expr --> Expr.Int 0
Expr.simplify_expr <-- Expr.Int 1
Expr.simplify_expr --> Expr.Int 1
Expr.simplify_expr --> Expr.Add (Expr.Int 1, Expr.Int 0)
Expr.simplify_expr <-- Expr.Int 4
Expr.simplify_expr --> Expr.Int 4
Expr.simplify_expr -->
  Expr.Mult (Expr.Int 4, Expr.Add (Expr.Int 1, Expr.Int 0))
- : Expr.expr = Expr.Mult (Expr.Int 4, Expr.Add (Expr.Int 1, Expr.Int 0))

我不知道,为什么在带有 1(第 9 行)的 eval 返回后,用 Add 调用了 simplify_expr。有人可以帮忙吗?

最佳答案

== 替换为 =。参见例如 Does != have meaning in OCaml? .

不是问题,还要检查 simplify_exprSubDivMinus 情况:0 - e2 不是 e2 并且 1/e2 不是 e2...

关于recursion - OCaml 递归函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13100503/

相关文章:

python - 不同的成对加法迭代失败 Python

javascript - 如何有效且高效地将项目分组到配对的存储桶中(如果存在)

node.js - 尝试使用聚合将集合复制到另一个集合时出错。

ruby-on-rails - 是否可以使用 "eval"来定义一个函数(而不是每个函数一个)?

java - 如何追踪递归?

c++ - C++中前缀表达式的递归评估

java - java中的递归调用导致不正确的行为

f# - 将面向铁路的故障跟踪转换为 Rx 友好错误

functional-programming - 为什么我们在Elm函数组合中不指定参数?

javascript - 避免在此模块中进行评估