返回OCaml中不同的第一类模块

时间:2015-10-28 13:58:27

标签: module ocaml

我想从函数中返回不同的模块。这是我希望工作的一般概念。

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)但它没有,因为在第一场比赛中确定了负荷的回归类型。我怎样才能使这个总体思路发挥作用?

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

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

2 个答案:

答案 0 :(得分:3)

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

这对我有用:

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返回的值。否则它们必须是相同的类型,它们不是。

答案 1 :(得分:3)

“好”的解决方案是为每个人使用相同的模块类型:

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)