如何从Ocaml类型中提取值

时间:2015-11-15 00:07:08

标签: ocaml

我有一个类型

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?

2 个答案:

答案 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 xVar y概括为两个表达式ee'

答案 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)