我是Ocaml的新手,在为lambda演算编写解释器时遇到了一个奇怪的错误。
let rec valof : exp -> env -> value =
fun exp env ->
match exp with
Var n -> exp2value (lookup env n)
| Lambda (name , body) -> Clos (name , body , env) (*some thing wrong here*)
| _ -> Err
;;
exp
,value
和env
的定义如下:
type exp =
Num of int
| Str of string
| Err
| Var of string
| Lambda of string * exp
| App of exp * exp
;;
type value =
Num of int
| Str of string
| Clos of string * exp * env
| Err
;;
type env =
Empty
| Cons of string * exp * env
;;
编译时,编译器抱怨解释器的lambda行:
Error: This expression has type env/1490
but an expression was expected of type env/1457
我搞砸了的任何想法? 谢谢!
答案 0 :(得分:1)
Error: This expression has type env/1490
but an expression was expected of type env/1457
当您在交互式顶层(REPL)中调试代码时,这种错误非常频繁,这意味着您声明了类型env
两次。如果您在REPL中复制粘贴代码,就会发生这种情况。
您不需要在每个语句后附加所有;;
。 OCaml编译器不需要它们。然而,因为;;
意味着它在顶层有用而且只在那里有用。
如您所知,在进行模式匹配或定义和类型时,可以省略第一个|
。但是,由于您希望在任何情况下都保持对齐,因此即使不是义务,也要将|
包含在每一行中,这通常被视为一种良好做法。
此处您的类型不是相互依赖,但value
取决于exp
和env
,并且取决于exp
,这意味着您必须谨慎声明类型按正确的顺序。但为了清楚起见,您可能希望以另一种更合乎逻辑的顺序呈现它们。 (我不是说这个顺序比另一个好,我只是想让你知道你可以使用以下语法)。
例如,如果你想要自上而下地呈现你的类型(从图片事物(即环境)到内部事物(即值)),你可以使用and
语法告诉你类型相互依赖的编译器。
type env =
| Empty
| Cons of string * exp * env
and exp =
| Num of int
| Str of string
| Err
| Var of string
| Lambda of string * exp
| App of exp * exp
and value =
| Num of int
| Str of string
| Clos of string * exp * env
| Err
最后,value
和exp
都包含以下构造函数Num of int
和Str of string
,OCaml无法判断Int 1
是否应为value
1}}或exp
。更确切地说,OCaml将选择构造函数Int
引用env
或exp
(它将选择的那个取决于您声明它们的顺序)。因此,主张为构造者选择不同的名称。