如何在ReasionML / BuckleScript中使用带有可选参数的函数来生成Js.t对象?

时间:2019-03-22 11:56:05

标签: polymorphism ocaml reason bucklescript value-restriction

我具有以下功能

[@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 个答案:

答案 0 :(得分:4)

这实际上与可选参数和curring无关,而是与值限制和非通用(即弱)类型变量有关。 TL; DR;通过添加参数getlet get () = route(~_method="GET") ();转换为语法函数,或为模块创建*.rei接口文件。

更长的故事

.. row variable表示一种多态类型,编译器无法将其简化为正常的单态类型(因为显然没有使用此函数),也不能相信部分应用程序{ {1}}实际上尚未访问route(~_method="GET")参数,可以将其存储在其中的某个位置,该参数应定义类型。

因此,编译器不能将其保留为多态变量,也不能提供具体类型,因此,它会生成弱类型变量,可以将其视为将来定义的具体混凝土的参考单元类型。就像未初始化的类型。稍后将通过使用options函数的代码对其进行初始化。如果最终没有使用过该类型,则可能会超出OCaml / Reason输入规则所禁止的模块范围。因此,您应该手动为它指定一个单型(即将其约束为某种单态类型),或者创建一个隐藏该值(即不存在)的接口文件,因此不会泄漏模块的范围。基本上,仅创建一个与您的get文件同名的空.mli/.rei文件即可解决此问题。另一个常见的解决方案是将.ml/.re转换为语法函数,即带有语法显式变量的内容,例如

get

进一步阅读