Задача проверки типа OCaml с функторами и вариантами полиморфизма c - PullRequest
0 голосов
/ 23 марта 2020

У меня проблема с использованием функторов в OCaml. У меня есть тип модуля TASK, который используется для выполнения различных задач:

module type TASK = sig
  type task_information
  type task_information_as_lists

  type abstract_u_set_type
  module AbstractUSet : Set.S with type t = abstract_u_set_type

  val mk_task_information : task_information_as_lists -> task_information
end

Модуль типа TASK будет содержать алгоритмы, использующие узлы. Эти узлы будут иметь разные типы. Поэтому я построил TASK_NODE:

module type TASK_NODE = sig
  type t
  val compare : t -> t -> int
  val to_string : t -> string
end

task_information_as_lists из TASK. Это будет список, содержащий разные типы, но у каждой задачи будут разные типы в этом списке. Поскольку я не могу иметь что-то вроде module Game : (TASK with with type u := int list) с функторами, я создал модуль типа INFO_CARRIER. Для каждого отдельного модуля типа TASK я хочу иметь отдельный модуль типа INFO_CARRIER, который будет содержать информацию о том, что на самом деле является типом task_information_as_lists.

Это тип модуля INFO_CARRIER:

module type INFO_CARRIER = sig
  module INODE : TASK_NODE
  type u = [`V of INODE.t list | `E of INODE.t] list
end

Для тестирования я хочу иметь string TASK_NODES и INFO_CARRIER, которые могут передавать тип u, например type u = [`V of string list | `E of string] list.

Итак, я построил StringTaskNode и StringInfoCarrier, а также StringTask для использования узлов:

module StringTaskNode : TASK_NODE = struct
  type t = string
  let compare = compare
  let to_string s = "Node " ^ s
end

module StringInfoCarrier (TN : TASK_NODE) : (INFO_CARRIER with module INODE = TN) = struct
  module INODE = TN
  type u = [`V of TN.t list | `E of TN.t] list
end

module StringTask (TN : TASK_NODE) (IC : INFO_CARRIER with module INODE = TN) : 
  (TASK with type task_information_as_lists := IC.u with type abstract_u_set_type := Set.Make(IC.INODE).t) = struct
  module N = IC.INODE
  module AbstractUSet = Set.Make(IC.INODE)

  type task_information = {v_nodes : AbstractUSet.t ; e_nodes : N.t}

  let mk_task_information info_list =
    match info_list with
    | (`V v)::(`E e)::[] -> {v_nodes = AbstractUSet.of_list v ; e_nodes = e;}
    | _ -> raise .... (* raising an error here *)
end

Затем у меня есть другой модуль ProdFP, который выполнит некоторые вычисления для задачи:

module ProdFP 
  (TN : TASK_NODE) 
  (IC : INFO_CARRIER with module INODE=TN) 
  (TA : TASK with type abstract_u_set_type:=u with type task_information_as_lists:=IC.u) = struct
  ...
end

Пока ошибок не происходит. Но когда я собираю все вместе в Test, я получаю:

Error: This expression has type
  [`E of string | `V of string list]
but an expression was expected of type
SIC.u = [`E of SIC.INODE.t | `V of SIC.INODE.t list]
Type string is not compatible with type
  SIC.INODE.t = STN.t

Это модуль тестирования:

module Test = struct
  module STN = StringTaskNode
  module SIC = StringInfoCarrier(STN)
  module ST = StringTask(STN)(SIC)
  module PF = ProdFP(STN)(SIC)(ST)

  let v_list =["a";"b"]
  let e = "c"
  let info_as_list = [`V v_list ; `E e]

  let info = ST.mk_task_information info_as_list (* THIS IS WHERE THE ERROR HAPPENS *)
end

Я знаю, это очень длинный пост, но я Я пытался включить столько информации, сколько необходимо. Было бы здорово, если бы вы могли мне помочь:)

1 Ответ

1 голос
/ 23 марта 2020

Похоже, что проблема заключается только в ограничении сигнатуры в определении модуля StringTaskNode:

module StringTaskNode : TASK_NODE = struct
...
end

Это ограничение делает тип StringTaskNode.t абстрактным и, таким образом, скрывает равенство STN.t = string. Снятие ограничения

module StringTaskNode = struct
...
end

должно решить эту проблему c.

...