Как я могу карри функцию с необязательными параметрами, которые генерируют объекты Js.t в ReasionML / BuckleScript? - PullRequest
2 голосов
/ 22 марта 2019

У меня есть следующая функция

[@bs.obj]
external route:
  (
    ~_method: string,
    ~path: string,
    ~action: list(string) => unit,
    ~options: Js.t({..})=?,
    unit
  ) =>
  _ =
  "";

Поскольку функции могут применяться частично, я ожидаю, что смогу сделать это:

let get = route(~_method="GET");

но это дает мне эту ошибку:

This expression's type contains type variables that can't be generalized:                                                
(~path: string, ~action: list(string) => unit, ~options: {_.. }=?,                                                       
unit) =>
{. "_method": string, "action": list(string) => unit,
  "options": Js.undefined({.. }), "path": string}

Что я здесь не так делаю?

1 Ответ

4 голосов
/ 22 марта 2019

На самом деле речь идет не о необязательных параметрах и карри, а об ограничении значений и не обобщенных, то есть слабых переменных типа. TL; DR; либо включите get в синтаксическую функцию, добавив параметр, например, let get () = route(~_method="GET") ();, либо создайте файл интерфейса *.rei для вашего модуля.

Более длинная история

Переменная строки .. обозначает полиморфный тип, который компилятор не может привести к нормальному мономорфному типу (поскольку эта функция явно не используется), и при этом он не может доверять частичному применению. route(~_method="GET") на самом деле еще не получил доступ к параметру options и может храниться где-то в нем, что должно определять тип.

Следовательно, компилятор не может оставить его как полиморфную переменную и не может дать конкретный тип, в результате он создает переменную слабого типа, которая может рассматриваться как ссылочная ячейка для будущего определенного бетона. тип. Как неинициализированный тип. Позже он будет инициализирован кодом, использующим функцию get. Если, в конце концов, тип никогда не используется, он может выйти за рамки модуля, что запрещено правилами ввода OCaml / Reason. Следовательно, вы должны либо присвоить ему монотип вручную (то есть ограничить его каким-либо мономорфным типом), либо создать файл интерфейса, в котором это значение скрыто (то есть отсутствует), и, следовательно, не может утечь область видимости модуля. По сути, просто создайте пустой файл .mli/.rei с тем же именем, что и ваш файл .ml/.re, чтобы решить эту проблему. Другим распространенным решением является превращение get в синтаксическую функцию, то есть что-то с синтаксически явными переменными, например,

let get () = route(~_method="GET") ();

Дальнейшее чтение

...