【问题标题】:Interpreting a function解释函数
【发布时间】:2012-03-07 01:21:56
【问题描述】:

我必须想出一个函数来评估抽象语法树并返回其评估结果。

evaluate 将具有类型 Exp -> int 选项

评估 (Prod(Num 5, Diff(Num 6, Num 1)));; 验证它:int option = Some 25

@约翰·帕尔默 我该怎么做呢?我可以使用模式匹配吗?如果是这样,我将如何做才能确定需要完成的操作。

这是我想出的?我仍然不明白每个说的代码。

let rec evaluate = function
 | Num n -> Some n
 | Neg e -> match evaluate e with
 |Sum (a,b) -> evaluate(a) + evaluate(b)
 |Diff(a,b) -> evaluate(a) - evaluate(b)
 | Prod (a,b) -> evaluate(a) * evaluate (b) 
 |Quot (a,b) -> evaluate(a) / evaluate(b) 

【问题讨论】:

    标签: f# f#-interactive


    【解决方案1】:

    以下是一些入门提示

    let rec evaluate AST =
       match AST with
       |Prod(a,b) -> evaluate(a) * evaluate(b)
       |Num(a) -> a
       ....
    

    编辑

    所以我假设你的数据类型看起来像

    type AST =
    |Num of int
    |Neg of AST
    |Prod of AST * AST
    |Diff of AST * AST
    |Quot of AST * AST
    |Sum of AST * AST
    

    所以你设置你的 AST(大概你是从某个地方解析这个 - 这是一个完全不同的问题)像

    let ast = Prod(Num 5, Diff(Num 6, Num 1))
    

    然后你可以定义评估为

    let rec evaluate arg =
        match arg with
        |Num n -> n
        |Neg tree -> - (evaluate tree)
        |Sum (a,b) -> (evaluate a) + (evaluate b)
        |Prod(a,b) -> (evaluate a) * (evaluate b)
        |Quot(a,b) -> (evaluate a) * (evaluate b)
        |Diff(a,b) -> (evaluate a) - (evaluate b)
    

    然后调用它并用

    打印结果
    printfn "%i" (evaluate ast)
    

    请注意,evaluate 必须具有 AST -> int 类型,否则您将需要处理选项情况 - 例如 2 * None2 + None 是什么

    我不确定你的意思

    我应该如何在较小的输入上调用递归方法。

    但希望这可以解释一切

    【讨论】:

    • evaluate 需要递归,即let rec evaluate ...
    • 好的,我让它与 int 一起工作,但我应该返回一些 int。现在,当我执行 |Num n -> Some n 我得到 ~vs3783.fsx(118,34): error FS0001: This expression was expected to have type int option but here has type Exp >
    • @user1072706 - 正如我在帖子中所说,如果您使用选项,您将不得不处理2 + None。运算符 +,*,/ 未仅针对 int Option 定义 int
    【解决方案2】:

    首先研究语法、词法分析器和解析器,以便为您生成 AST。一旦你有了它,就很简单地遍历树并评估它。

    这是一个指向 F# 的链接:

    http://www.quanttec.com/fparsec/

    【讨论】:

    • 听起来他们已经有了 AST,只是想评估一下。
    【解决方案3】:

    我发布了一个用 OCaml 编写的小型解释器,用于小型函数式语言 here。请特别注意 eval 函数。您的问题更简单,因为您没有变量,因此您不需要我拥有的 vars 字典,并且您总是返回 int 结果,因此您不需要 value 联合类型。

    要评估一个整数表达式,您只需评估子表达式并用它们做一些简单的事情。这是最优雅的模式匹配:

    type Expr =
      | Int of int
      | Neg of Expr
      | Add of Expr * Expr
      | Mul of Expr * Expr
    
    let rec eval = function
      | Int n -> n
      | Neg f -> -eval f
      | Add(f, g) -> eval f + eval g
      | Mul(f, g) -> eval f * eval g
    

    例如:

    Mul(Int 2, Neg(Int 3)) |> eval
    

    模式匹配的优点是您可以根据数据结构的内容和形状添加更复杂的操作。例如:

    | Add(f, Neg g) -> eval f - eval g
    

    在不知不觉中你正在做computer algebra

    【讨论】:

      猜你喜欢
      • 2012-11-10
      • 2017-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多