Seneca
Seneca

Reputation: 2412

OCaml/reason design modules

I'm coming from a Javascript background & I'm trying to understand how I need to structure/build a program with Reason/Ocaml's module system.

As an exercise let's say I want to write this piece of javascript in OCaml/Reason (will compile it back to js through js_of_ocaml)

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

How should I design my program to accomplish this?

Should I make a module which takes another module to produce a GraphQLObjectType in js through js_of_ocaml?

How would I structure this type that backs a 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 */

I mean fields is a thunk which returns a map that contains an unknown amount of fields. (every graphqlobject has different fields) To what type does this map in OCaml/Reason, do I need to make my own?

Upvotes: 1

Views: 280

Answers (1)

ivg
ivg

Reputation: 35210

Just for you to feel the flavor of OCaml, the direct (syntactic) translation would be:

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

Basically, I mapped js objects to OCaml's records. There are also objects in OCaml with methods and inheritance, but I think that records are still a closer abstraction. The records can be seen as a named tuple, and, of course, can contain functions. Modules, are more heavy weight abstractions, that is also a collection of fields. Unlike records, modules may contain types, other modules, and basically any other syntactic construction. Since types are removed at compile time, the runtime representation of a module is absolutely the same as the representation of records. Modules also define namespaces. Since OCaml records are defined by the names of their fields, it is always useful to define each records in its own module, e.g.,

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

Upvotes: 1

Related Questions