"Конструктор несвязанного типа _no_unused_value_warning" (только когда используется файл)
Рассмотрим это очень простое определение модуля:
module type My_test = sig
type config with sexp
end;;
Когда я непосредственно ввожу это в приглашении utop, все работает нормально:
utop # module type My_test = sig
type config with sexp
end;;
module type My_test =
sig type config val config_of_sexp : Sexp.t -> config val sexp_of_config : config -> Sexp.t end
Но когда я пытаюсь #use
файл, содержащий точно такое же определение, я получаю Unbound type constructor _no_unused_value_warning_
ошибка:
utop # #use "dummy.mli";;
File "dummy.mli", line 2, characters 7-13:
Error: Unbound type constructor _no_unused_value_warning_
(строка 2 type config with sexp
)
Информация о версии: The universal toplevel for OCaml, version 1.7, compiled for OCaml version 4.01.0
ОБНОВИТЬ:
Я начинаю вознаграждение, так как я действительно заинтересован в
- зная, является ли это ошибкой OCaml
- разумные обходные пути / исправления для моего кода
2 ответа
1) Верхний уровень ocaml имеет две недокументированные опции: -dsource & -dparsetree
2) Если я включаю -dsource, а затем попробуйте #use "dummy.mli". Я увидел, что сгенерированный источник выглядит так:
$ ocaml -dsource
# #use "dummy.mli";;
module type My_test =
sig
type config
val config_of_sexp : (Sexplib.Sexp.t -> config) _no_unused_value_warning_
val sexp_of_config : (config -> Sexplib.Sexp.t) _no_unused_value_warning_
end;;
File "dummy.mli", line 1, characters 31-37:
Error: Unbound type constructor _no_unused_value_warning_
3) однако, когда я непосредственно ввел объявление типа непосредственно в верхний уровень, сгенерированный источник не имел "_no_unused_value_warning_"
4) Дерево разбора, сгенерированное для этих двух случаев, немного отличается из-за наличия _no_unused_value_warning_.
5) После некоторого greping я увидел, что библиотека type_conv вставляет `'val name: _no_unused_value_warning_' как своего рода хак для деактивации предупреждений - https://github.com/janestreet/type_conv/blob/master/lib/pa_type_conv.ml - в строке 916 есть комментарий, который объясняет это (я все еще изучаю ocaml, так что я еще не все понимаю в этих частях)
Поскольку sexplib использует type_conv, эта подпись была добавлена в этом случае.
6) Но реальная проблема здесь заключается в том, как ocaml toplevel обрабатывает директиву #use и непосредственно вводит строки кода.
В этом файле: https://github.com/diml/ocaml-3.12.1-print/blob/master/toplevel/opttoploop.ml- use_file (в строке 316) использует List.iter для циклического перемещения по списку Parsetree.toplevel_phrase и вызывает execute_phrase для каждого элемента. Цикл REPL (в строке 427) вызывает execute_phrase для одного Parsetree.toplevel_phrase
7) Я до сих пор не уверен, что на самом деле вызывает разницу в дереве разбора, но попытаться выяснить это было интересно.
Было бы замечательно, если бы кто-то, кто разбирается в этих частях, опубликовал ответ.
Я столкнулся с этим сегодня, используя Utop 1.17 с Ocaml 4.02.1. После прочтения отличного ответа gautamc'e я попробовал этот простой обходной путь:
utop # type 'a _no_unused_value_warning_ = 'a;;
Это позволило мне успешно использовать модуль, с которым у меня были проблемы.