Понимание функторов в OCaml - PullRequest
8 голосов
/ 25 июля 2010

Я застрял со следующей проблемой функторов в OCaml.Я вставляю часть кода, чтобы вы поняли.В основном

Я определил эти два модуля в pctl.ml:

module type ProbPA = sig
  include Hashtbl.HashedType  
  val next: t -> (t * float) list
  val print: t -> float -> unit
end

module type M = sig
  type s  
  val set_error: float -> unit
  val check: s -> formula -> bool
  val check_path: s -> path_formula -> float
  val check_suite: s -> suite -> unit
end

и следующем функторе:

module Make(P: ProbPA): (M with type s = P.t) = struct
  type s = P.t
  (* implementation *)
end

Затем, чтобы фактически использовать эти модули, я определил новыймодуль непосредственно в файле с именем prism.ml:

type state = value array
type t = state
type value =
  | VBOOL of bool
  | VINT of int
  | VFLOAT of float
  | VUNSET
(* all the functions required *)

Из третьего источника (formulas.ml) я использовал функтор с модулем Prism:

module PrismPctl = Pctl.Make(Prism)
open PrismPctl

И, наконец, изmain.ml

open Formulas.PrismPctl
(* code to prepare the object *)
PrismPctl.check_suite s.sys_state suite (* error here *)

и компиляция выдает следующую ошибку

Ошибка: это выражение имеет массив типа Prism.state = Prism.value, но ожидалось выражение типа Formulas.PrismPctl.s

Из того, что я могу понять, есть некое плохое совмещение имен, они одинаковы (поскольку value array - это тип, определенный как t, и он используется M with type s = P.tв функторе), но средство проверки типов не считает их одинаковыми.

Я действительно не понимаю, в чем проблема, кто-нибудь может мне помочь?

Заранее спасибо

Ответы [ 2 ]

6 голосов
/ 25 июля 2010

(Вы публикуете некомпилируемый код. Это плохая идея, потому что людям может быть труднее помочь вам, и потому что иногда достаточно просто свести вашу проблему к простому примеру, чтобы решить ее. Но я думаю, что вы видитесложность в любом случае.)

Внутри formulas.ml, Окамл видит это PrismPctl.s = Pctl.Make(Prism).t = Prism.t;первое равенство из определения PrismPctl, а второе равенство из сигнатуры Pctl.Make (в частности, with type s = P.t бит).

Если вы не пишете файл mliдля Formulas ваш код должен скомпилироваться.Таким образом, проблема должна заключаться в том, что файл .mli, который вы написали, не упоминает правильное равенство.Вы не показываете свои .mli файлы (вы должны, они являются частью проблемы), но, вероятно, вы написали

module PrismPctl : Pctl.M

Этого недостаточно: когда компилятор компилирует main.ml, онничего не знаю о PrismPctl, который не указан в formulas.mli.Вам нужно указать либо

module PrismPctl : Pctl.M with type s = Prism.t

, либо, если вы включили with type s = P.t в подпись Make в pctl.mli

module PrismPctl : Pctl.M with type s = Pctl.Make(Prism).s
2 голосов
/ 25 июля 2010

Это проблема, с которой я столкнулся, когда узнал больше об этом. При создании функтора вы выставляете сигнатуру функтора, в данном случае M. Он содержит абстрактный тип s, параметризованный функтором, и что-либо более конкретное не доступно снаружи. Таким образом, доступ к любому элементу записи s (как в sys_state) приведет к ошибке типа, как вы столкнулись.

Остальное выглядит хорошо. Определенно трудно правильно использовать функторы, но помните, что вы можете манипулировать только экземплярами типа, параметризованного функтором, через интерфейс / сигнатуру, предоставляемые функтором.

...