ocaml类型推断中的匿名变量

时间:2017-09-04 21:38:34

标签: ocaml type-inference

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

expvalueenv的定义如下:

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

我搞砸了的任何想法? 谢谢!

1 个答案:

答案 0 :(得分: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语法告诉你类型相互依赖的编译器。

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

最后,valueexp都包含以下构造函数Num of intStr of string,OCaml无法判断Int 1是否应为value 1}}或exp。更确切地说,OCaml将选择构造函数Int引用envexp(它将选择的那个取决于您声明它们的顺序)。因此,主张为构造者选择不同的名称。