【问题标题】:anonymous variables in ocaml type inferenceocaml 类型推断中的匿名变量
【发布时间】:2017-09-04 21:38:34
【问题描述】:

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

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

【问题讨论】:

  • 这意味着env 被声明了两次,在不同范围内的不同行上。这两种类型同名,但不相等。
  • (将此作为答案:-)
  • 明天我会找到一些合适的参考文献,然后写一篇。

标签: ocaml type-inference


【解决方案1】:
Error: This expression has type env/1490 
but an expression was expected of type env/1457

当您在交互式顶层 (REPL) 中调试代码时,这种错误非常常见,这意味着您两次声明了类型 env。如果您将代码复制粘贴到 REPL 中,就会发生这种情况。


您不需要在每个语句之后附加所有;;。 OCaml 编译器不需要它们。尽管如此,由于;; 意味着它在顶层有用且仅在顶层有用。


如您所知,当您进行模式匹配或定义 sum 类型时,可以省略第一个 |。但是,由于您希望在任何情况下都保持对齐,因此通常认为在每行包含 | 是一种好习惯,即使这不是义务。


这里你的类型不是相互依赖的,但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 还是 exp。更准确地说,OCaml 将选择构造函数 Int 引用 envexp (它将选择哪个取决于您声明它们的顺序)。因此提倡为构造函数取不同的名字。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-24
    相关资源
    最近更新 更多