Как исправить ошибку компиляции OCaml при использовании аннотаций типов с функторами? - PullRequest
0 голосов
/ 18 января 2019

Я новичок в OCaml и пытаюсь использовать функторы.Когда я использую аннотации типа модуля с функторами, это приводит к ошибке времени компиляции в моем коде.

Когда я удаляю : Printable (из строки module FromToString) и : ToString (изmodule IntToString строка), следующая программа компилируется без ошибок:

module type ToString =
sig
    type t
    val to_string: t -> string
end

module type Printable =
sig
    type t
    val print: t -> unit
end

module FromToString (S:ToString) : Printable  =
struct
    type t = S.t
    let print a = print_string ( S.to_string a) 
end

module IntToString : ToString =
struct
    type t = int
    let to_string = string_of_int
end

module PrintableInt = FromToString(IntToString)
let () = PrintableInt.print 3

Однако, когда я добавляю эти аннотации (как показано в коде), компилятор выдает следующую ошибку:

File "Functor.ml", line 26, characters 28-29:
Error: This expression has type int but an expression was expected of type
         PrintableInt.t = FromToString(IntToString).t

Как я могу использовать эти аннотации, не вызывая ошибки компиляции?

Ответы [ 2 ]

0 голосов
/ 18 января 2019

Необходимо сделать тип t общедоступным, используя обозначение with:

module type ToString =
sig
    type t
    val to_string: t -> string
end

module type Printable =
sig
    type t
    val print: t -> unit
end

module FromToString (S:ToString) : Printable with type t = S.t =
struct
    type t = S.t
    let print a = print_string ( S.to_string a) 
end

module IntToString : ToString with type t =int  =
struct
    type t = int
    let to_string = string_of_int
end

module PrintableInt = FromToString(IntToString)
let () = PrintableInt.print 3
0 голосов
/ 18 января 2019

Основная проблема заключается в том, что ограничения вашей подписи делают полученный модуль слишком непрозрачным. Когда вы ограничиваете свой функтор, результат:

 module FromToString (S:ToString) : Printable = ...

вы делаете тип t абстрактным типом, который может использоваться только функцией to_string и никогда не создается. Другими словами, модуль типа Printable сам по себе непригоден.

При запуске с функтором очень часто полезно посмотреть на тип модуля, выведенный компилятором для результирующего модуля. В случае FromToString это:

module FromToString (S:ToString) : sig
  type t = S.t
  val print: t -> unit
end = ...

Вы можете видеть, что предполагаемый тип модуля результата

 sig
   type t = S.t
   val print: t -> unit
 end

что он очень похож на Printable за исключением того, что теперь тип t равен типу t модуля аргумента S.

Таким образом, можно повторно использовать Printable для записи полного типа модуля результата, добавив равенство типов с ограничением with:

  module FromToString (S:ToString): Printable with type t = S.t = struct
    type t = S.t
    let print a = print_string ( S.to_string a) 
  end

Та же проблема возникает для IntToString и может быть исправлена ​​аналогичным образом:

module IntToString : ToString with type t = int =
struct
    type t = int
    let to_string = string_of_int
end

Тогда ошибка компилятора исчезла:

module PrintableInt = FromToString(IntToString)
let () = PrintableInt.print 3
...