странное поведение OCaml при написании функции двумя разными способами - PullRequest
0 голосов
/ 24 февраля 2019

У меня есть следующий код (который работает):

type a = A of int
let print = ref (fun _ -> ())
let f x = !print (A x)

Но следующее не работает:

let print = ref (fun _ -> ())
type a = A of int
let f x = !print (A x)

Мне интересно, почему при обмене двумя строками код приводит кбыть недействительным

Спасибо!

РЕДАКТИРОВАТЬ: при запуске второго кода я получаю следующую ошибку:

Error: This expression has type a but an expression was expected of type 'a
       The type constructor a would escape its scope

1 Ответ

0 голосов
/ 24 февраля 2019

Вкратце, тип ссылки должен быть определен до ее создания: вы должны иметь возможность комментировать тип print при первом его определении.И, поменяв определения a и print, вы сделали эту последнюю точку невозможной:

  let print: ( ??? -> unit) ref  = ref (fun _ -> ())
  type a = A of int

Здесь ??? должно быть a, но тип a еще предстоитбыть определенным.

Точнее, типы в OCaml имеют область видимости, чтобы определять, когда локальный тип выходит за пределы контекста, где он определен и имеет смысл.Например,

let x =
  let module M = struct type t = A end in
  M.A

завершается ошибкой с той же ошибкой, что и во втором примере

Ошибка: это выражение имеет тип Mt, но ожидалось выражение типа 'a Конструктор типа Mtэкранировать область действия

Здесь разрешить типу M.t экранировать тело определения x было бы плохо, поскольку модуль M и, следовательно, тип M.t не определены внеэтого определения.

Ваш пример терпит неудачу по той же причине.Переменная

let print = ref (fun _ -> ())

имеет тип ('_weak1 -> unit) ref, где '_weak1 - это тип заполнителя для еще неизвестного типа.Но будущий тип ссылки уже должен существовать в этой точке.

Таким образом, когда вы определяете новый тип

type t = A of int

и пытаетесь присвоить этот тип слабому типу '_weak1переменная,

let print': (t -> unit) ref = print

проверка типов жалуется, что тип t был неопределен при создании переменной типа '_weak1:

Ошибка: это выражение имеет тип ('weak1-> unit) ref, но ожидалось выражение типа (t -> unit) ref Конструктор типа t выйдет из области видимости

Аналогично, ваша функция f

 let f x = !print (A x)

подразумевает, что тип !print будет t -> unit и приведет к аналогичной ошибке:

Ошибка: это выражение имеет тип t, но ожидалось выражение типа 'weak1 Конструктор типат выйдет за рамки

...