繁体   English   中英

OCaml 函数式语言的表达式错误

[英]Expression Error on OCaml functional language

我在 OCaml 中定义了一个原始类型,这是一个家庭作业。 一切正常,但我在实现 Dict 类型时遇到错误。 编码:

type ide = string;;

type exp = Eint of int | Ebool of bool | Den of ide | Prod of exp * exp | Sum of exp * exp | Diff of exp * exp |
    Eq of exp * exp | Minus of exp | IsZero of exp | Or of exp * exp | And of exp * exp | Not of exp |
    Ifthenelse of exp * exp * exp | Let of ide * exp * exp | Fun of ide * exp | FunCall of exp * exp |
    Letrec of ide * exp * exp| Dict of (ide * exp) list;;

type 't env = ide -> 't;;
let emptyenv (v : 't) = function x -> v;;
let applyenv (r : 't env) (i : ide) = r i;;
let bind (r : 't env) (i : ide) (v : 't) = function x -> if x = i then v else applyenv r x;;

type evT = Int of int | Bool of bool | Unbound | FunVal of evFun | RecFunVal of ide * evFun | DictVal of (ide * evT) list
and evFun = ide * exp * evT env;;

let typecheck (s : string) (v : evT) : bool = match s with
    "int" -> (match v with
        Int(_) -> true |
        _ -> false) |
    "bool" -> (match v with
        Bool(_) -> true |
        _ -> false) |
    _ -> failwith("not a valid type");;


let prod x y = if (typecheck "int" x) && (typecheck "int" y)
    then (match (x,y) with
        (Int(n),Int(u)) -> Int(n*u))
    else failwith("Type error");;

let sum x y = if (typecheck "int" x) && (typecheck "int" y)
    then (match (x,y) with
        (Int(n),Int(u)) -> Int(n+u))
    else failwith("Type error");;

let diff x y = if (typecheck "int" x) && (typecheck "int" y)
    then (match (x,y) with
        (Int(n),Int(u)) -> Int(n-u))
    else failwith("Type error");;

let eq x y = if (typecheck "int" x) && (typecheck "int" y)
    then (match (x,y) with
        (Int(n),Int(u)) -> Bool(n=u))
    else failwith("Type error");;

let minus x = if (typecheck "int" x) 
    then (match x with
        Int(n) -> Int(-n))
    else failwith("Type error");;

let iszero x = if (typecheck "int" x)
    then (match x with
        Int(n) -> Bool(n=0))
    else failwith("Type error");;

let vel x y = if (typecheck "bool" x) && (typecheck "bool" y)
    then (match (x,y) with
        (Bool(b),Bool(e)) -> (Bool(b||e)))
    else failwith("Type error");;

let et x y = if (typecheck "bool" x) && (typecheck "bool" y)
    then (match (x,y) with
        (Bool(b),Bool(e)) -> Bool(b&&e))
    else failwith("Type error");;

let non x = if (typecheck "bool" x)
    then (match x with
        Bool(true) -> Bool(false) |
        Bool(false) -> Bool(true))
    else failwith("Type error");;


let rec eval (e : exp) (r : evT env) : evT = match e with

    Dict(pairs) -> DictVal(evalDictList pairs r) |
    Eint n -> Int n |
    Ebool b -> Bool b |
    IsZero a -> iszero (eval a r) |
    Den i -> applyenv r i |
    Eq(a, b) -> eq (eval a r) (eval b r) |
    Prod(a, b) -> prod (eval a r) (eval b r) |
    Sum(a, b) -> sum (eval a r) (eval b r) |
    Diff(a, b) -> diff (eval a r) (eval b r) |
    Minus a -> minus (eval a r) |
    And(a, b) -> et (eval a r) (eval b r) |
    Or(a, b) -> vel (eval a r) (eval b r) |
    Not a -> non (eval a r) |
    Ifthenelse(a, b, c) -> 
        let g = (eval a r) in
            if (typecheck "bool" g) 
                then (if g = Bool(true) then (eval b r) else (eval c r))
                else failwith ("nonboolean guard") |
    Let(i, e1, e2) -> eval e2 (bind r i (eval e1 r)) |
    Fun(i, a) -> FunVal(i, a, r) |
    FunCall(f, eArg) -> 
        let fClosure = (eval f r) in
            (match fClosure with
                FunVal(arg, fBody, fDecEnv) -> 
                    eval fBody (bind fDecEnv arg (eval eArg r)) |
                RecFunVal(g, (arg, fBody, fDecEnv)) -> 
                    let aVal = (eval eArg r) in
                        let rEnv = (bind fDecEnv g fClosure) in
                            let aEnv = (bind rEnv arg aVal) in
                                eval fBody aEnv |
                _ -> failwith("non functional value")) |
        Letrec(f, funDef, letBody) ->
                (match funDef with
                    Fun(i, fBody) -> let r1 = (bind r f (RecFunVal(f, (i, fBody, r)))) in
                                                    eval letBody r1 |
                    _ -> failwith("non functional def"))            

    and evalDictList (pairs : (ide * exp) list) (r : evT env) : (ide * evT) list = match pairs with
        [ ] -> [ ] |
        (key,value) :: other -> (key, eval value r) :: evalDictList other r;;

一切正常,但是当我这样做时:

let mydict = Dict("test", Eint 2);;

Dict("test", Eint 2);;

我收到此错误:错误:此表达式的类型为 'a * 'b,但期望表达式为 (ide * exp) 列表类型。

这个作业包括为具有上述原始类型的语言编写一个基本的解释器。

该错误比实际需要的更笼统和模糊,但直接指向问题。 如果我将错误中的类型变量'a'b替换为实际类型,您可能会立即看到它:

错误:此表达式的类型为 ide * exp,但应为 (ide * exp) 列表类型的表达式。

也就是说,您给Dict一个元组(某事物),但它期望一个元组列表(具有某些特定类型),因为它被定义为Dict of (ide * exp) list

将元组包装在列表中将使其编译:

let mydict = Dict [("test", Eint 2)];;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM