В чем смысл предупреждения 40: эта запись... содержит поля, которые не видны в текущей области
Обратите внимание на следующий код:
module A =
struct
type r = { i : int; s: string }
end
module B =
struct
type r = { i : int; s : string }
end
let f (x : A.r) : B.r = match x with
{ i; s } -> { i = 2*i; s = "" }
Два модуля определяют точно такую же запись. Функция f преобразует запись A в запись B. Предупреждение уже выдается во время компиляции, но также доступно в интерактивном режиме. В ocaml cli кажется, что вызов f делает предполагаемое:
# let x = f { i = 5; s = "ab" };;
Characters 10-29:
let x = f { i = 5; s = "ab" };;
^^^^^^^^^^^^^^^^^^^
Warning 40: this record of type Shadow.A.r contains fields that are
not visible in the current scope: i s.
They will not be selected if the type becomes unknown.
val x : Shadow.B.r = {Shadow.B.i = 10; s = ""}
Я нашел запись в блоге lexifi.com, которая объясняет проблему и некоторые распространенные решения. То, что я не понимаю, является фактическим сообщением об ошибке:
- Что означает, что тип становится неизвестным?
- Что означает, когда поле не выбрано?
- И в результате двух выше: какие условия необходимо выполнить, чтобы игнорировать предупреждение?
Ответы
Ответ 1
Тип записи известен в этом случае, потому что вы предоставили аннотации.
Если вы удалите аннотации, тип станет неизвестным, и значение кода может измениться.
Философия OCaml заключается в том, что добавление и удаление аннотаций типа не должно влиять на смысл программы, поэтому возникает предупреждение.
Вы можете избежать этого предупреждения, введя соответствующее поле в область видимости. Выполнение этого для поля, которое определено в модуле A
, включает либо открытие A
, чтобы привести его содержимое в область видимости, либо определить имя поля с модулем. Например:
module A = struct ... end
let test r = r.A.field
let test2 r = let open A in r.field
open A
let test3 r = r.field