2017-09-04 47 views
4

我是Ocaml的新手,当我为lambda微积分编写解释器时遇到了一个奇怪的错误。ocaml类型推断中的匿名变量

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 
;; 

编译时,编译器抱怨上解释的拉姆达行:

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 
;; 

expvalueenv就像定义

Error: This expression has type env/1490 
     but an expression was expected of type env/1457 

在那里我搞砸任何想法向上? 谢谢!

+4

这意味着'env'被声明了两次,在不同范围的不同行上。这两种类型具有相同的名称,但不相等。 – Bergi

+0

(使这个答案:-) –

+0

明天我会找到一些适当的参考,然后写一个。 – Bergi

回答

1
Error: This expression has type env/1490 
but an expression was expected of type env/1457 

这种错误是很常见的,当你在一个交互式顶层(REPL)调试代码,它意味着你声明的类型env两次。如果您将代码复制到REPL中,就会发生这种情况。


在每个语句之后,您不需要附加所有那些;;。 OCaml编译器不需要它们。尽管如此,因为;;这意味着它在上层和唯一有用。


大家知道,第一|可以当你正在做的图案匹配或当要定义总和类型删去。但是,既然您想在任何情况下保持对齐方式,即使不是义务,也可以在每条线上包含|,这被认为是一种好的做法。


这里你类型不是相互依靠,但value取决于expenv,并取决于exp这意味着你必须小心声明的正确顺序的类型。但为了清楚起见,您可能想要以另一种更合理的顺序呈现它们。 (我不是说这个顺序比另一个更好,我只是想让你知道你可以使用下面的语法)。例如,如果要将自上而下的类型(从图片事物(即环境))展示给内部事物(即值),可以使用and语法,该语法告诉编译器:类型取决于彼此。

​​

最后一件事,既valueexp包含以下构造Num of intStr of string,OCaml中无法分辨Int 1应该是valueexp。更确切地说,OCaml将选择构造函数Int参考envexp(它将选择的取决于您声明它们的顺序)。因此提倡为构造函数选择不同的名称。