Объединение без тегов из привязки javascript идет по неправильному пути

Я пытаюсь написать привязку ReasonML для пакета amqplib npm:

http://www.squaremobius.net/amqp.node/

В частности, эта функция:

http://www.squaremobius.net/amqp.node/channel_api.html#channel_get

class type amqpMessageT = [@bs] {
  pub content: nodeBuffer
};

type amqpMessage = Js.t(amqpMessageT);

type gottenMessage = Js.Nullable.t(amqpMessage);

type qualifiedMessage = Message(gottenMessage) | Boolean(bool);

class type amqpChannelT = [@bs] {
  pub assertQueue: string => queueParams => Js.Promise.t(unit);
  pub consume: string => (amqpMessage => unit) => unit;
  pub ack: amqpMessage => unit;
  pub get: string => Js.Promise.t(qualifiedMessage);
  pub purgeQueue: string => Js.Promise.t(unit);
  pub deleteQueue: string => Js.Promise.t(unit);
  pub sendToQueue: string => nodeBuffer => messageParams => unit;
};

И тогда у меня есть следующий код:

 ....
 channel##get("MyQueue")
 |> Js.Promise.then_(message => {
   switch message {
     | Boolean(false) => Js.Promise.resolve(Js.log("No Message"));
     | Message(msg) => Js.Promise.resolve(Js.log("Has Message, Will Travel"));
     | Boolean(true) => Js.Promise.resolve(Js.log("Impossible Message"!));
   }
  }

Однако это идет по пути «Сообщение (msg)» всегда, даже когда вызов js возвращает false.

Теперь добавляем следующую привязку:

let unsafeGet: amqpChannel => string => Js.Promise.t(gottenMessage) = [%bs.raw{|function(channel, queueName) {
  return channel.get(queueName).then((value) => {
    if(value === false) {
      return Promise.resolve(null)
    } else {
      return Promise.resolve(value)
    }
  })
}|}];

Мне удалось обойти проблему, но я не большой поклонник использования bs.raw, если честно. В чем проблема с моим первоначальным типом объединения без тегов? Как я могу решить эту проблему?


person Abraham P    schedule 18.07.2018    source источник


Ответы (1)


В языке OCaml нет нетегированного типа объединения и нет информации о типах времени выполнения, поэтому вам придется реализовать свой собственный тип, проверки и преобразования, чтобы привести их в удобную форму.

Например, вы можете использовать абстрактный тип для представления «неизвестного» типа и функцию-компаньон, чтобы проверить его тип, привести его к этому типу, а затем преобразовать в qualifiedMessage:

type unknownMessage;

let classifyMessage = (value: unknownMessage) =>
  switch (Js.Types.classify(value)) {
  | JSString(s) => Message(Js.Nullable.return(s))
  | JSNull      => Message(Js.null)
  | JSFalse     => Boolean(false)
  | JSTrue      => Boolean(true)
  | _           => failwith("invalid runtime type")
  }

Кроме того, в качестве побочного примечания, если вы абстрагируете базовую структуру данных, раскрывая абстрактные типы и функции/внешние объекты вместо предоставления «сырых» объектов, вы получите большую гибкость в том, как вы определяете интерфейс, и можете скрыть это дополнительное преобразование. шаг.

person glennsl    schedule 30.07.2018