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

时间:2016-06-09 16:18:56

标签: ocaml hashtable

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

2 个答案:

答案 0 :(得分:2)

让我们举个例子:

如果我写

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,因此解释器会尝试告诉您类型都被命名为{{ 1}}但不一样。

[编译]

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

<强> typea.ml

t

<强> typeb.ml

type t = A
let x = A

<强> main.ml

type t = B
let y = B

如果我编译它,我将

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中,一个在标准库中)而OCaml没有傻瓜,男孩,他知道你什么时候出错,但他很难理解,因为他只会说那些能听到的人。 :-D

P.S。 :您的Core_kernel.Std出现错误,因为它没有返回选项但会找到找到的值,或者如果找不到值则引发Hashtbl.find例外。我也纠正了它。 ; - )

答案 1 :(得分:-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

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