如何使用可选参数对在 ReasionML/BuckleScript 中生成 Js.t 对象的函数进行 curry?

Posted

技术标签:

【中文标题】如何使用可选参数对在 ReasionML/BuckleScript 中生成 Js.t 对象的函数进行 curry?【英文标题】:How can I curry a function with optional parameters that generates Js.t objects in ReasionML/BuckleScript? 【发布时间】:2019-08-13 09:50:03 【问题描述】:

我有以下功能

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

我在这里做错了什么?

【问题讨论】:

Why does OCaml sometimes require eta expansion?的可能重复 添加到上面链接的答案中,开放对象类型,无论是否包含在Js.t 中,都包含一个隐式类型变量,因此Js.t(..) 是更明确的形式Js.t(.. as 'a)。我的猜测是,编译器不会将与对象关联的类型变量与任何其他类型变量区分开来,因此从它的角度来看,类型变量很可能被 ref('a) 替换,这可能会导致问题。 不太可能会有对编译器内部有深入了解的人来纠正我,这就是为什么我添加了 ocaml 标签来引起他们的注意:) 【参考方案1】:

这实际上不是关于可选参数和柯里化,而是关于值限制和非泛化,也就是弱类型变量。 TL;博士;要么通过添加参数将get 转换为语法函数,例如let get () = route(~_method="GET") ();,要么为您的模块创建一个*.rei 接口文件。

更长的故事

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

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

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

进一步阅读

https://ocamlverse.github.io/content/weak_type_variables.html http://caml.inria.fr/pub/docs/manual-ocaml/polymorphism.html#sec51 https://v1.realworldocaml.org/v1/en/html/imperative-programming-1.html#side-effects-and-weak-polymorphism

【讨论】:

以上是关于如何使用可选参数对在 ReasionML/BuckleScript 中生成 Js.t 对象的函数进行 curry?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用可选参数创建端点? (节点、快递、MongoDB)

如何使用 swagger 在路径中定义可选参数

如何在 NestjS 中使用可选的 url 参数

如何使用可选参数构建装饰器? [复制]

如何获取可选参数的默认值?

如何使用 JavaScript 创建具有多个可选参数的搜索?