我有一个类型
type expr =
Const of int
| Var of string
| Bin of expr * binop * expr
也
type binop =
Plus
| Minus
| Mul
| Div
和
type value =
Int of int
| Closure of env * string option * string * expr
Binop对两个exps执行一个操作,我需要编写一个eval函数,它接受一个闭包和expr并返回一个值
离。
let evn = [("z1",Int 0);("x",Int 1);("y",Int 2);("z",Int 3);("z1",Int 4)];;
val evn : (string * Nano.value) list =
[("z1", Int 0); ("x", Int 1); ("y", Int 2); ("z", Int 3); ("z1", Int 4)]
# let e1 = Bin(Bin(Var "x",Plus,Var "y"), Minus, Bin(Var "z",Plus,Var "z1"));;
val e1 : Nano.expr =
Bin (Bin (Var "x", Plus, Var "y"), Minus, Bin (Var "z", Plus, Var "z1"))
# eval (evn, e1);;
- : Nano.value = Int 0
我遇到的问题是函数需要返回INT int而不是实际值。
这是我到目前为止所写的
let rec eval (evn,e) = match e with
| Const a -> Int a
| Var x-> Int (lookup (x,evn) )
| Bin( Var x, Plus, Var y) -> Int ( eval(evn,Var x) + eval(evn,Var y) )
| Bin( Var x, Minus, Var y) -> Int ( eval(evn,Var x) + eval(evn,Var y) )
| Bin( Var x, Mul, Var y) -> Int ( eval(evn,Var x) + eval(evn,Var y) )
| Bin( Var x, Div, Var y) -> Int ( eval(evn,Var x) + eval(evn,Var y) )
;;
lookup在闭包evn中查找x并返回其值 我遇到的问题是我需要在bin匹配中执行整数运算,但是因为eval返回值的类型我不能这样做。我如何更改最后四个匹配中的代码,以使其能够执行算术并在完成后返回int类型的int?
答案 0 :(得分:1)
你需要像
这样的东西let x =
match eval (evn, Var x) with
| Int x -> x
| _ -> failwith "runtime error"
in
let y =
match eval (evn, Var y) with
| Int y -> y
| _ -> failwith "runtime error"
in
Int (x + y)
在每个比赛案例中。您可能应该将此模式匹配分解为可以重复调用的函数:
let get_int = function
| Int i -> i
| _ -> failwith "runtime error: expected an integer"
... Int ((eval (evn, e1) |> get_int) + (eval (evn, e2) |> get_int))
您必须在评估程序中执行此运行时检查是有意义的 - 在您的表示中,没有理由不能将变量映射到evn
中的闭包而不是整数
另请注意,与您的问题相反,evn
本身并非封闭。它通常被称为"环境"。闭包是由Closure
构造的值,它们带有环境,除此之外 - 我认为你只是有一个错字。
我假设您将来会将Var x
和Var y
概括为两个表达式e
和e'
。
答案 1 :(得分:1)
let rec eval (evn,e) = match e with
| Const a -> Int a
| Var x-> Int (lookup (x,evn) )
| Bin( el, Plus, er) ->
let Int cl=eval (evn,el ) and Int cr=eval (evn,er ) in
Int (cl+cr)
| Bin( el, Minus, er) ->
let Int cl=eval (evn,el ) and Int cr=eval (evn,er ) in
Int (cl-cr)
| Bin( el, Mul, er) ->
let Int cl=eval (evn,el ) and Int cr=eval (evn,er ) in
Int (cl*cr)
| Bin( el, Div, er) ->
let Int cl=eval (evn,el ) and Int cr=eval (evn,er ) in
Int (cl/cr)