2016-06-09 1 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 

Это потому, что в интерпретаторе вы можете объявить несколько типов с тем же именем и ассоциированных значений для этих типов. Но здесь, как вы можете видеть, x и y не одного типа, но оба типа называются 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

Well , Я не интерпретировал код, но компилировал, поэтому не уверен, применима ли первая часть вашего ответа, но вторая часть имеет смысл. Я понял, что это должно быть связано с каким-то именем, но не понимал, что это связано с открытием пространства имен. Спасибо за указание на это (и коррекцию PS также). Теперь мне просто нужно выяснить, как улучшить мои сообщения об ошибках (например, ваши: D) –

+0

BTW, могу ли я предложить отредактировать ваш ответ и удалить «интерпретированную» часть? Я не уверен, что это полезно для всех, кто мог бы побывать на тех же проблемах, что и я, и найти этот вопрос. Тем не менее, это ваш вызов о том, как редактировать. Ура! –

+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