OCaml/reason 设计模块

OCaml/reason design modules

我有 Javascript 的背景并且我正在尝试了解我如何需要 structure/build 具有 Reason/Ocaml 模块系统的程序。

作为练习,假设我想在OCaml/Reason中编写这段javascript(将通过js_of_ocaml将其编译回js)

var TeaType = new GraphQLObjectType({
     name: 'Tea',
     fields: () => ({
       name: {type: GraphQLString},
       steepingTime: {type: GraphQLInt},
   }),
}); 

我应该如何设计我的程序来完成这个?

我是否应该制作一个模块,该模块需要另一个模块通过 js_of_ocaml 在 js 中生成 GraphQLObjectType?

我将如何构造支持 GraphQLObjectType 的这种类型?

Tea.re
let name = "Tea";
let fields = /* what type should I make for this? Tea is 
             just one of the many graphql-types I'll probably make */

我的意思是 fields 是一个 thunk,它 returns 一个包含 未知数量的 字段的地图。 (每个 graphqlobject 都有不同的字段) 此地图在 OCaml/Reason 中映射到什么类型,我需要自己制作吗?

为了让你感受一下OCaml的味道,直译(句法)是:

   let tea_type = GraphQL.Object.{
      name = "Tea";
      fields = fun () -> QraphQL.Field.[{
           name = GraphQL.Type.{name : GraphQL.string }
           steeping_time = GraphQL.Type.{name : QraphQL.int }
      }]
   }

基本上,我将js对象映射到OCaml的记录中。 OCaml 中也有带有方法和继承的对象,但我认为记录仍然是更接近的抽象。记录可以看作是命名元组,当然可以包含函数。模块,是比较重量级的抽象,也就是字段的集合。与记录不同,模块可以包含类型、其他模块以及基本上任何其他句法结构。由于类型在编译时被删除,因此模块的运行时表示与记录的表示完全相同。模块还定义名称空间。由于 OCaml 记录是由它们的字段名称定义的,因此在其自己的模块中定义每个记录总是有用的,例如,

module GraphQL = struct
  let int = "int"
  let string = "string"

  module Type = struct
    type t = {
      name : string
    }
  end

  module Field = struct 
    type t = {
      name : string;
      steeping_time : Type.t
    }
  end

  module Object = struct 
    type t = {
      name : string;
      fields : unit -> Field.t list
  end
end