Search code examples
ocamlexternalffibucklescriptreason-react

Understanding ReasonML/Bucklescript Externals


Just trying to generally understand what is going on here. Does this make sense to explain ReasonApolloTypes.gql as an example of using Externals.

This is the bs.module code

[@bs.module] external gql : ReasonApolloTypes.gql = "graphql-tag";

bs.module tells buckelscript that we want to use a FFI.

external tells bs the name of the FII we want to use and we set its value to ReasonApolloTypes.gql which is a globally available Reason module that we installed when we added reason-apollo in bsconfig's bs-dependencies array, and to package.json. If you open node_modules/reason-apollo/src you will see defined Reason modules that are globally available like any other.

ReasonApolloTypes.re is listed there and contains a defined type named gql. So ReasonApolloType.gql is the named module we are accessing with external gql. In ReasonApolloType.gql there is a defined type, type gql = [@bs] (string => queryString);. This tell bucklescript to assign a type of string to the gql type and the assign the value to querystring, so type querystring is of type string. Then set ReasonApolloTypes.gql to use the "graphql-tag" node library to resolve ReasonApolloTypes.gql.

Am I missing an concepts here? Is this expressed correctly? The Bucklescript/Reason docs are above my head for Externals at this point. Thanks.


Solution

  • This question is really not very appropriate on SO (see what's on-topic here), and should perhaps be asked on the Discord instead. But here's what it means:

    • external tells the compiler we're defining something that's "external", ie. that we want to use FFI.

    • [@bs.module] tells BuckleScript that what we're referencing is a module, and that it will need to emit require calls when it's used.

    • gql is the name we're going to use to refer to it on the Reason side.

    • : means we're specifying the type of the external. ReasonApolloTypes.gql is a type defined in the ReasonApolloTypes module.

    • = "graphql-tag" tells the compiler that what we're referencing is named graphql-tag on the JavaScript side.

    Furthermore, type gql = [@bs] (string => queryString); specifies that it is a function from string to queryString, and [@bs] means it should use the uncurried calling convention when calling this function.

    So, on the ML side, gql is a function that takes a string and returns a queryString. When called:

    let qs = [@bs] gql("some string"); /* [@bs] because it's uncurried */
    

    BuckleScript will generate something like this:

    var qs = require("graphql-tag")("some string");
    

    PS: In general, I'd advise you to start with something simpler to try to understand the FFI system. Trying to understand everything at once makes for a very steep learning curve and drastically increases the cost of small misunderstandings, because they tend to accumulate.