我怎样才能使用可选参数在ReasionML / BuckleScript中生成Js.t对象的函数?

How can I curry a function with optional parameters that generates Js.t objects in ReasionML/BuckleScript?

提问人:fhdhsni 提问时间:3/22/2019 最后编辑:glennslfhdhsni 更新时间:3/23/2019 访问量:719

问:

我有以下功能

[@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}

我在这里做错了什么?

多态性 OCaml 原因 BuckleScript 值限制

评论

0赞 glennsl 3/22/2019
为什么 OCaml 有时需要 eta 扩展的可能重复?
0赞 glennsl 3/22/2019
为了添加到上面链接的答案中,打开的对象类型,无论是否包装,都包含隐式类型变量,因此采用更显式的形式。我的猜测是,编译器不会将与对象关联的类型变量与任何其他类型变量区分开来,因此从它的角度来看,类型变量很可能被替换为 ,这可能会导致问题。Js.tJs.t({..})Js.t({..} as 'a)ref('a)
0赞 glennsl 3/22/2019
不过,对编译器内部有深入了解的人来纠正我并非不可能,这就是为什么我添加了 ocaml 标签以引起他们的注意:)

答:

4赞 ivg 3/22/2019 #1

这实际上不是关于可选参数和咖喱,而是关于值限制和非泛化(又名弱)类型变量。TL;博士;通过添加参数(例如,)转换为语法函数,或者为您的模块创建接口文件。getlet get () = route(~_method="GET") ();*.rei

长话短说

row 变量表示编译器无法将该多态类型简化为普通的单态类型(因为显然没有使用此函数),也不能信任分部应用程序实际上尚未访问该参数,并且可能存储在其中的某个位置,该参数应定义类型。..route(~_method="GET")options

因此,编译器不能将其保留为多态变量,也不能给出具体类型,因此,它会产生一个弱类型变量,该变量可以看作是未来定义的具体类型的参考单元。就像未初始化的类型一样。稍后将由使用该函数的代码对其进行初始化。如果在一天结束时从未使用过该类型,则它可能会超出模块的范围,这是 OCaml/Reason 类型规则所禁止的。因此,您要么手动给它一个单型(即,将其约束为某个单态类型),要么创建一个接口文件,其中该值是隐藏的(即不存在),因此不能泄漏模块的作用域。基本上,只需创建一个与文件同名的空文件即可解决此问题。另一个常见的解决方案是转换为句法函数,即具有句法显式变量的东西,例如,get.mli/.rei.ml/.reget

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

延伸阅读