OCaml Hashtbl/0.t 和 Hashtbl/-1.t

OCaml Hashtbl/0.t and Hashtbl/-1.t

我对 OCaml 很陌生,所以我不确定以下错误消息的含义(特别是 /0/-1):

Error: This expression has type (string, string) Hashtbl/0.t
       but an expression was expected of type ('a, 'b) Hashtbl/-1.t

我正在将 Hashtbl.t 传递给 Hashtbl.find,但出现了这个错误。我不清楚 /0/-1 是如何出现的,以及它们的实际含义。

这是一个演示我的问题的最小工作示例:

open Core_kernel.Std

let file_to_hashtbl filename =
  let sexp_to_hashtbl_str = Sexplib.Conv.hashtbl_of_sexp
      string_of_sexp string_of_sexp
  in In_channel.with_file
    filename ~f:(fun ch -> (Sexp.input_sexp ch |> sexp_to_hashtbl_str))

let ht = file_to_hashtbl "test"

let t1_val = match Hashtbl.find ht "t1" with
  | Some v -> v
  | None -> assert false

let () = print_endline t1_val

显然,这只是缺少半列的问题,以下代码可以编译:

open Core_kernel.Std;;

let file_to_hashtbl filename =
  let sexp_to_hashtbl_str = Sexplib.Conv.hashtbl_of_sexp
      string_of_sexp string_of_sexp
  in In_channel.with_file
    filename ~f:(fun ch -> (Sexp.input_sexp ch |> sexp_to_hashtbl_str));;

let ht = file_to_hashtbl "test"

let t1_val = match Hashtbl.find ht "t1" with
  | Some v -> v
  | None -> assert false

let () = print_endline t1_val

但是,我也不知道如何解释错误信息。

让我们举个例子:

如果我写

type t = A;;
let x = A;;
type t = B;;
let y = B;;
x = y;;
Error: This expression has type t/1561 but an expression was expected of type
     t/1558

这是因为在解释器中,您可以声明具有相同名称的多个类型并将值关联到这些类型。但是在这里,正如您所看到的,xy 不是同一类型,但是这两种类型都被命名为 t 因此解释器试图告诉您这些类型都被命名为 t 但不一样。

[编译]

如果我想编译它,我必须声明

typea.ml

type t = A
let x = A

typeb.ml

type t = B
let y = B

main.ml

open Typea
open Typeb

x = y

如果我编译这个我会得到

Error: This expression has type Typeb.t
   but an expression was expected of type Typea.t

你应该从中吸取什么教训? 停止解释,编译!

现在我成功地编译了你的文件,我也遇到了一个错误,但更明确:

 Error: This expression has type (string, string) Hashtbl.t
   but an expression was expected of type
     ('a, 'b) Core_kernel.Std.Hashtbl.t =
       ('a, 'b) Core_kernel.Core_hashtbl.t

[解释与更正]

因为我太好了,这是您更正的文件:

let file_to_hashtbl filename =
  (* open the namespace only where needed *)
  let open Core_kernel.Std in
  let sexp_to_hashtbl_str = Sexplib.Conv.hashtbl_of_sexp
                              string_of_sexp string_of_sexp
  in In_channel.with_file
       filename ~f:(fun ch -> (Sexp.input_sexp ch |> sexp_to_hashtbl_str));;

let ht = file_to_hashtbl "test"

let t1_val = 
  try
    Hashtbl.find ht "t1" 
  with Not_found -> assert false

let () = print_endline t1_val

您的错误是您将 Core_kernel.Std 作为全局命名空间打开,因此当您编写 Hashtbl.find 时,它首先在 Core_kernel.Std 中查找,而不是在标准库中查找。

我所做的是在需要它的函数中打开 Core_kernel.Std,而不是在整个文件中(所以它是一个本地命名空间)(养成的好习惯 ).

所以,如您所见,问题是您有两个类型 Hashtbl.t 的定义(一个在 Core_kernel.Std 中,一个在标准库中)并且 OCaml 不是傻瓜,男孩,他知道你什么时候错了,但他很难理解,因为他只为那些能听到的人说话。 :-D

P.S。 : 你的 Hashtbl.find 中有一个错误,因为它没有 return 一个选项,而是找到的值,或者如果没有找到值则引发 Not_found 异常。我也纠正了它。 ;-)