0

I'm using @glennsl's bs-json module to decode some JSON responses, but all the JSON responses have some common fields in addition to their unique payload. Furthermore, the JSON responses (via XMLHTTPRequest) are different depending on whether they're successful or not: they wouldn't include the 'body element.

I'm wondering if there's a way I can create method to take on a decoder for the generalized format. I was think something along the lines of:

module Decode {
    type msgCheck = {
        success:    bool,
        command:    string,
        errmsg:     string,
        errnum:     int,
    };
    // type msgComplete('body) = {
    //     success:    bool,
    //     command:    string,
    //     errmsg:     string,
    //     errnum:     int,
    //     body:       'body,  /* This is what the incoming JSON looks like. */
    // }
    let msgCheck = json => Json.Decode.{
        success:    json |> field("success",        bool),
        command:    json |> field("command",        string),
        errmsg:     json |> field("error_string",   string),
        errnum:     json |> field("error",          int),
    };
    
    let jsonDecode = ('body, bodyDecoder, response) => {
        let msgCheck = response -> msgCheck;

        switch msgCheck.success {
            | true  => {
                let (r:'body) = response -> bodyDecoder;
                return (true, Some(r))  /* returning body (only) preferable. */
            }
            | false => {
                Js.log(msgCheck.errmsg);
                return (false, None)
            }
        }
    };
}

Is there a way make a template method in reasonml? Or, should just wrap the 'body type in an option element and use optional() in the field() calls?

glennsl
  • 28,186
  • 12
  • 57
  • 75
Jamie
  • 7,075
  • 12
  • 56
  • 86
  • I'm not really sure what you're asking. What is a template method? Can you provide the full interface/signature of the function you want? – glennsl May 31 '21 at 18:20
  • Also not sure why you're returning both a `bool` and an `option`, when it seems like the latter (already) carries the same information. – glennsl May 31 '21 at 18:21
  • @glennsl You're right about the tuple - shortly after posting I changed the code, dropping the boolean. And as far as "template methods" : I was thinking along the lines of C++ templates. TBH I'm probably going to withdraw the question. – Jamie Jun 01 '21 at 22:19
  • Right, you don't need to do anything to make a function "generic" or polymorphic. The compiler will automatically infer the most general type for the function. So if you have a `bookDecoder` that is `Js.Json.t => foo`, the type of `jsonDecode` applied to that will effectively be `((Js.Json.,t => foo), Js.Json.t) => option(foo)` (after removing the `'body` argument, which shouldn't be there, and the tuple) – glennsl Jun 02 '21 at 07:33
  • Ahh ... okay .. yes. Could I partially apply the method, with the specific decoder? So `let generalDecode = ((Js.Json.t => {thing}), Js.Json.t) => option{thing}` with partial applications `let fooOpt = generalDecode(fooDecoder);` and `let barOpt = generalDecode(barDecoder);`? – Jamie Jun 02 '21 at 14:58
  • Absolutely. Just like that. – glennsl Jun 02 '21 at 16:00

0 Answers0