OCaml 中 Return 个不同的前 class 个模块

Return different first class modules in OCaml

我想 return 来自一个函数的不同模块。这是我希望可行的总体思路。

module type First = sig
  val speak : unit -> unit
end
module First = struct
  let speak () = print_endline "hi"
end

module type Second = sig
  val another_speaker : unit -> unit
end
module Second = struct
  let another_speaker () = print_endline "another hi"
end

type mods = First | Second


let load = function
  | First -> (module First : First)
  | Second -> (module Second : Second)

1) 但这不是因为加载的 return 类型在第一次匹配时就确定了。我怎样才能使这个总体想法可行?

2) 我怎样才能写出这样的东西并让它发挥作用。

type a = [`First of (module type First )]

您不能将这两种模块类型视为同一类型,因为它们是不同的。但是你可以将它们组合成一个变体类型。

这对我有用:

module type First = sig
  val speak : unit -> unit
end

module type Second = sig
  val another_speaker : unit -> unit
end

type modvar = MFirst of (module First) | MSecond of (module Second)

type mods = First | Second

module First = struct
  let speak () = print_endline "hi"
end

module Second = struct
  let another_speaker () = print_endline "another hi"
end

let load = function
| First -> MFirst (module First)
| Second -> MSecond (module Second)

我不确定这是否是您要找的。

更新

下面是使用多态变体重写的相同代码:

module type First = sig
  val speak : unit -> unit
end

module type Second = sig
  val another_speaker : unit -> unit
end

type mods = First | Second

module First = struct
  let speak () = print_endline "hi"
end

module Second = struct
  let another_speaker () = print_endline "another hi"
end

let load = function
| First -> `MFirst (module First: First)
| Second ->`MSecond (module Second: Second)

关键是你需要标记load返回的值。否则它们必须是同一类型,但它们不是。

"good"解决方案是为每个人使用相同的模块类型:

module type S = sig
  val speak : unit -> unit
end

module First = struct
  let speak () = print_endline "hi"
end
module Second = struct
  let speak () = print_endline "another hi"
end

type mods = First | Second

let load = function
  | First -> (module First : S)
  | Second -> (module Second : S)

实在不行的话,除了Jeffrey给出的变种方案,还有GADT方案:

type 'a t = First : (module First) t | Second : (module Second) t

let load : type a . a t -> a = function
  | First -> (module First : First)
  | Second -> (module Second : Second)