polymorphism - 如何柯里化(Currying)带有可选参数的函数,以在 ReasionML/BuckleScript 中生成 Js.t 对象?

标签 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}

我在这里做错了什么?

最佳答案

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

更长的故事

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

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

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

进一步阅读

关于polymorphism - 如何柯里化(Currying)带有可选参数的函数,以在 ReasionML/BuckleScript 中生成 Js.t 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55299097/

相关文章:

haskell - 程序程序员的功能代码片段列表?

OCaml 作为编译目标

types - 将多个变体合并为一个变体

ocaml - 如何请求变量的类型类?

c++ - 包含指向多态类的指针的 vector

java - 一个适配器多种数据类型 - android

java - 如何根据参数类型选择重载方法?

java - 替换 Java Bean 的 instanceof

ocaml - Ocaml 如何决定用户定义运算符的优先级?

reactjs - 如何在 React 和 ReasonML 中使用 SVG?