Распаковка модуля первого класса, ограниченного переменной типа - PullRequest
1 голос
/ 11 октября 2019

Я пытаюсь написать функцию, которая в основном выглядит следующим образом:

module type M = sig
  type t
  val doStuff : t -> unit
end

let f : 'a. 'a -> (module M with type t = 'a) -> unit
      = fun value (module MSomething) -> MSomething.doStuff value

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

Тип этого упакованного модуля содержит переменные

Однако я обнаружил, что все еще могу заставить это работать, еслиЯ оборачиваю его в GADT, который 1) делает 'a экзистенциальным и 2) предоставляет преобразователь из другой параметризованной переменной типа в экзистенциальный:

type 'b gadt =
  GADT: ('b -> 'a) * (module M with type t = 'a) -> 'b gadt

let f value (GADT (convert, (module MSomething))) =
  MSomething.doStuff (convert value)

Сам GADT не является помехой 1 , но я бы очень хотел избежать использования функции convert, поскольку она не предназначена для каких-либо целей, кроме как для помощи компилятору. Возможно ли это как-то?

Полный пример / MCVE

module type M = sig
  type t
  val doStuff : t -> unit
end

module MInt = struct
  type t = int
  let doStuff = print_int
end

let f : 'a. 'a -> (module M with type t = 'a) -> unit
      = fun value (module MSomething) -> MSomething.doStuff value

let () = f 42 (module MInt : M with type t = int)
let () = print_newline ()

1 Я на самом деле хочу GADT, потому что мне нужно, чтобы модуль был параметризован другим экзистенциалом, чтобы я мог соединить модули разных типовв списке. Но для простоты я опустил это в первом примере выше.

1 Ответ

2 голосов
/ 11 октября 2019

С модулями первого класса (как и для любого локального модуля) вы должны обращаться к локально абстрактным типам, а не к явным полиморфным аннотациям:

let f (type a) (value:a) (module M: M with type t = a) = M.doStuff value

работает просто отлично.

...