0

我了解在 OCaml 中有 和 的interfaces概念module

我现在明白如何使用它们了。

但是,我不明白如何充分利用它们。


例如,在 Java 中,假设我们有一个接口,并且Map我们也有一个实现。HashtableHashMapMap

在代码中,我可以这样做:

Map m = new Hashtable();
m.put("key", value);

有一天,如果我改变主意,我可以Hashmap通过更改为 来快速更改Map m = new Hashtable();Map m = new HashMap();,对吗?


但是我怎样才能在 Ocaml 中轻松做到这一点?

例如,我在 OCaml 中有MapSig和 'HashMap:MapSig and "Hashtable:MapSig

如何轻松更改实现?

我认为我不能,因为在 OCaml 中我必须这样做:

let m = Hashtable.create ();;

Hashtable.put m key value;;

如果我想HashMap改用,我必须将代码中的每个替换为,对吗HashtableHashMap


编辑:

我不仅在寻找一种为模块创建别名的方法。我还考虑了实现的有效性,即实现是否遵循所需的接口。

例如,在上面的 Java 示例中,只有HashMap实现了Map接口,我才能替换HashtableHashMap. 否则,Java 编译器会报错。

但是如果我module M = Hashtable在 OCaml 中这样做,并且如果HashMap不遵循MapSig并且我替换HashtableHashMap,会发生什么?我认为编译器不会抱怨,对吧?

4

3 回答 3

1

从 3.12.1 开始,OCaml 允许使用以下语法来打开和别名模块:

let foo .... =
  let module HashTable = HashMap in (* magic is here *)
  let h = HashTable.create () in
  ....

所以你只需要在你使用它的地方重命名你正在使用的模块。

于 2013-02-21T14:23:58.047 回答
1

这是一个示例,显示了我认为您要求的内容:

# module type HASH = sig type t val hash : t -> int end ;;
module type HASH = sig type t val hash : t -> int end
# module I = struct type t = int let hash i = i end ;;
module I : sig type t = int val hash : 'a -> 'a end
# module J = struct type t = int end ;;
module J : sig type t = int end
# module M : HASH = I ;;
module M : HASH
# module N : HASH = J ;;
Error: Signature mismatch:
       Modules do not match: sig type t = int end is not included in HASH
       The field `hash' is required but not provided

额外的“ : HASH”指定模块必须匹配 HASH 签名(并且它也将其限制为该签名)。

顺便说一句,我相信 OCaml 模块系统因其表现力而闻名于世(至少在模块系统圈子中)。我仍然是初学者,但值得学习。

于 2013-02-21T20:54:20.193 回答
0

您的 Java 示例和 OCaml 之间最直接的对应关系是使用函子(OCaml 将模块之间的静态函数称为模块)。因此,假设您在 OCaml 中实现了以下内容:

module type Map = sig
  (* For simplicity assume any key and value type is allowed *)
  type ('k, 'v) t

  val make : unit -> ('k, 'v) t
  val put : ('k, 'v) t -> ~key:'k -> ~value:'v -> unit
end

module Hashtable : Map = struct ... end
module HashMap : Map = struct ... end

然后你会写一个这样的函子:

module MyFunctor(Map : Map) = struct
  let my_map =
    let map = Map.make () in
    Map.put map ~key ~value;
    map
end

然后你将使用仿函数实例化一个模块:

module MyModule = MyFunctor(Hashtable)

瞧,改变实现是一个单行差异,因为两个模块实现都符合Map签名:

module MyModule = MyFunctor(HashMap)
于 2020-04-25T04:38:12.210 回答