Ocaml抽象类型和类型推断

时间:2017-07-04 12:36:41

标签: types ocaml

我对OCaml中的抽象类型有疑问。

假设我有一个隐藏某种类型的模块:

module Test : sig
  type t
  val make_t : unit -> t
end = struct
  type t = int option
  let make_t () = Some 42
end

我还有一个操作选项的功能:

let do_work : 'a option -> unit = function
  | Some x -> Printf.printf "Some\n"
  | None   -> Printf.printf "None\n"

毫不奇怪,当我在 t 实例上调用 do_work 时,我遇到了类型错误:

let () =
  do_work @@ Test.make_t ()
  

错误:此表达式的类型为Test.t,但表达式的类型为'一个选项

在我的应用程序中,我 t int选项更复杂,我不想向外暴露其内部。但是,我想告诉OCaml编译器 t 实际上是某个选项。我怎样才能做到这一点?

5 个答案:

答案 0 :(得分:4)

如果您不想公开您的实现,但是您需要使类型与其他类型兼容,请编写函数以转换为这些类型/从这些类型转换:

module Test : sig
  type t
  val make_t : unit -> t
  val to_option : t -> int option (* Signature *)
end = struct
  type t = int option
  let make_t () = Some 42
  let to_option t = t (* Implementation *)
end

然后,当您特别需要int option

let () =
  Test.make_t ()
  |> Test.to_option
  |> do_work

这样,您的类型Test.t保持抽象,这意味着您可以在不更改界面的情况下更改您的实现,只要您在转换器中执行必要的操作以保持其一致性。

答案 1 :(得分:4)

最直接的方法是只制作选项abstract的内容类型:

module Test :
sig
  type t'
  type t = t' option
  val make_t : unit -> t
end =
struct
  type t' = int
  type t = t' option
  let make_t () = Some 42
end

答案 2 :(得分:3)

您希望将t设为私有类型:

module T : sig
  type t = private int option
  val mk: unit -> t
end = struct
  type t = int option
  let mk () = Some 42
end

let do_work: int option -> unit =
  function
  | None -> print_endline "None"
  | Some i -> print_endline (string_of_int i)

let () =
  do_work (T.mk () :> int option)

与抽象类型解决方案一样,它允许对t实例的创建进行一些控制,但允许解构此类实例(封装可防止)。

答案 3 :(得分:2)

除了此处已有的好答案,如果您只关心某些内容是Some _还是None,您可以将其添加到您的界面:

module Test : sig
  type t
  val make_t : unit -> t
  val is_some : t -> bool
end = struct
  type t = int option
  let make_t () = Some 42
  let is_some = function
    | Some _ -> true
    | None -> false
end

(当然你可以将is_some重命名为与你的抽象相匹配的东西)

答案 4 :(得分:1)

或者你可以提供一个抽象来允许在

中应用正确类型的函数
ROLE_SUPER_ADMIN

操作员可能有点太多但看起来更酷。 另外,您可能需要查看monad。