在OCaml中管理动态依赖关系

在OCaml中管理动态依赖关系,ocaml,opam,Ocaml,Opam,想象一下OCaml中的一个库可能需要将其数据存储在某个地方。这个持久层可以用不同的库(sqlite、MySQL、PostgreSQL等)实现。根据具体的存储技术,它可能提供不同的功能和性能保证 管理此类库的外部依赖关系的可能方法有哪些?假设我使用MySQL开发,我不想在sqlite上引入编译时和运行时依赖关系 在C++中,我可以使用抽象接口,并将具体逻辑放入有条件地包含在项目中的模块(取决于配置开关)。我很好奇,任何人都会如何在OCaml中完成相同的任务。您可能会定义一个模块类型来对所有实现进行

想象一下OCaml中的一个库可能需要将其数据存储在某个地方。这个持久层可以用不同的库(sqlite、MySQL、PostgreSQL等)实现。根据具体的存储技术,它可能提供不同的功能和性能保证

管理此类库的外部依赖关系的可能方法有哪些?假设我使用MySQL开发,我不想在sqlite上引入编译时和运行时依赖关系


<>在C++中,我可以使用抽象接口,并将具体逻辑放入有条件地包含在项目中的模块(取决于配置开关)。我很好奇,任何人都会如何在OCaml中完成相同的任务。

您可能会定义一个模块类型来对所有实现进行抽象。e、 g

module type DB =
  sig
    type t
    type results

    val execute : t -> string -> results
    ...
  end
然后编写代码,将此模块类型的实现作为参数:

 module MyProg (D : DB) = struct
   let run db =
     let r = D.execute db "SELECT ..." in
     ...
 end
对于图书馆来说,这就是你所需要的。对于一个可执行程序,您需要一个单独的主函数来连接到一些实际的数据库,这些数据库可能是特定于数据库的,但其余的代码只使用抽象的
DB


(当然,你应该使用比这个基于字符串的API更好的API。这只是一个简单的例子。)

如果你知道你永远不会在同一个程序中同时使用两个后端,那么你也可以定义一个由不同后端实现的通用接口,并在编译时链接正确的接口。优点是不需要在DB参数上对整个代码库进行函数化。第一类模块也有助于避免对整个程序进行函数化