所以在我学习的课程中,我们尝试用 f# 编写一个解释器。为此我们必须制作一个小型计算器。 为此,我得到了这个代码:
type Value = INT of int
type Binop = BPLUS | BMINUS | BTIMES
type Rop = RSUM | RPROD | RMAX | RARGMAX
type vname = string
type Exp =
| CONSTANT of Value
| VARIABLE of vname
| OPERATE of Binop * Exp * Exp
| LET_IN of vname * Exp * Exp
| OVER_LIST of Rop * Exp list //must be non-empty
| OVER_RANGE of Rop * vname * Exp * Exp * Exp
(* An association list mapping variable names to their values. *)
type SymTab = (vname * Value) list
(* Inserts a variable into the variable table. *)
let bind v k vtab = (v, k) :: vtab : SymTab
(* Look up the value of a variable. *)
let rec lookup v = function
| (v', k) :: vtab -> if v = v' then k else lookup v vtab
| _ -> failwith ("unbound variable: " + v)
(* EVALUATION *)
(*****************************************************
* TODO: Task 2: complete the definition of `eval`. You may also
* define any auxiliary functions as you see fit, to help express `eval`
* as cleanly and concisely as possible.
****************************************************)
(* The evaluation function. *)
let rec eval (vtab : SymTab) (e : Exp) : Value =
match e with
| CONSTANT n -> n
| VARIABLE v -> failwith "case for VARIABLE not handled"
我们必须自己定义变量和一些其他函数。
对于变量,我的想法是使用模式匹配,就像他们在讲座中所做的那样。
所以像这样
| VARIABLE v ->
match lookup v vtab with
| Some x -> x
| None -> failwith "Unknown variable."
因此,如果查找给出一个变量,我只返回该变量,如果没有,我返回一个错误,说它不存在。
但是当我这样做时我得到
“这个表达式的预期类型是
‘价值’
但这里有类型
‘‘一个选项’”
请不要只写出解决方案,但如果您能给出一些关于为什么这不起作用的提示,我会非常高兴。
据我了解您的代码,
vtab
是一个由元组列表(将变量与值映射)表示的符号表。您的 lookup
函数搜索符号表以查看是否找到给定变量,如果找到,则返回其值(类型为 Value
)。如果没有,您的代码将引发异常。稍后,在您的代码中,您期望使用 option<Value>
类型,正如 @Gus 指出的那样。
当找不到变量时,您不应在
lookup
中抛出异常,而应该返回 None
,以便它符合函数式风格以及您管理模式的想法 VARIABLE
。因此,我鼓励您修改代码以免引发异常。
例如,
let rec lookup v = function
| (v', k) :: vtab -> if v = v' then Some k else lookup v vtab
| _ -> None
如果您有权使用,您还应该使用已经可以实现您想要的功能的数据类型(例如Map)。