2016-06-09 16 views
0

我很新的OCaml的,所以我不知道下面的錯誤消息意味着什麼(特別是/0/-1):OCaml的Hashtbl/0.t和Hashtbl/-1.t

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 
+0

我確定你使用的是解釋器,請參閱我的答案;-) – Lhooq

回答

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,因此解釋器試圖告訴您類型都被命名爲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中發生錯誤,因爲如果未找到任何值,它將不會返回選項,而會返回找到的值或引發Not_found異常。我也糾正了它。 ;-)

+0

,我沒有解釋代碼,但正在編譯,所以我不確定你的答案的第一部分是否適用,但第二部分是有意義的。我意識到這一定是由於某些名字衝突造成的,但是並沒有意識到這是由於命名空間的開放。感謝您指出了這一點(以及PS修正)。現在我只需要弄清楚如何讓我的錯誤信息更好地顯示出來(比如你的:D) –

+0

順便說一句,我可以建議編輯你的答案並刪除「解釋」部分?我不確定對於像我一樣可能遇到同樣問題的任何人都有用,並找到這個問題。但是,這是您如何編輯的呼叫。乾杯! –

+0

我會做的。你的編譯器是什麼? – Lhooq

-1

顯然,這僅僅是一個缺少半支柱的事,foloowing代碼編譯:

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 

但是,我做不知道如何解釋錯誤信息。

+0

在函數的末尾添加';;'將使_never_錯誤的輸入更正... – Lhooq