如何使用Js.Option.map?
How to use Js.Option.map?
对于此代码:
// val map : ('a -> 'b [@bs]) -> 'a option -> 'b option
let optTest: Js.Option.t(int) = Js.Option.map(x => x, Js.Option.some(1));
我收到以下错误:
This expression should not be a function, the expected type is (. 'a) => 'b
其中 x => x
为红色。我真的很困惑,为什么 map
不起作用?从它的类型签名看来我使用它是正确的,但编译器说第一个参数不应该是一个函数?
简答 - 使用Belt.Option.map
代替:
let optTest: option(int) = Belt.Option.map(Some(1), x => x);
长答案:
Js
命名空间主要用于绑定到 JavaScript 的标准 API。虽然 Js.Option
由于历史原因被包含在此命名空间中,但 Js
命名空间中使用的约定仍然是非常薄的绑定。
您在文档中看到的回调函数类型 'a -> 'b [@bs]
和您在错误消息中看到的类型 (. 'a) => 'b
是完全相同的类型。但前者是 OCaml 的语法,而后者是 Reason 的语法,并且还加糖以减少攻击性。无论哪种方式,问题是当它期望这种奇怪的其他类型的函数时,你传递给它的是一个普通函数。
另一种奇怪的函数称为 uncurried 函数。之所以这样称呼是因为 Reason 中的 "normal" 函数是柯里化的,而 JavaScript 函数不是。因此,未柯里化的函数本质上只是一个原生 JavaScript 函数,您有时需要处理它,因为您可能会收到一个函数或需要将一个函数传递给更高阶的 JavaScript 函数,例如 Js
命名空间。
那么如何在 Reason 中创建一个未柯里化的函数呢?只需添加一个 .
,如类型:
let optTest: option(int) = Js.Option.map((.x) => x, Some(1);
或者如果你想不加糖(你不加糖,但为了完整起见):
let optTest: option(int) = Js.Option.map([@bs] x => x, Some(1);
附录:
您可能已经注意到,我已将示例中的 Js.Option.t
和 Js.Option.some
替换为 option
和 Some
。那是因为那些是实际的基元。 option
类型本质上定义为
type option('a) =
| Some('a)
| None
随处可见。
Js.Option.t('a)
(和Belt.Option.t('a)
)只是一个别名。 Js.Option.some
只是一个方便的函数,在 Belt.Option
中没有任何等价物。它们主要只是为了保持一致性,您通常应该改用实际的类型和变体构造函数。
对于此代码:
// val map : ('a -> 'b [@bs]) -> 'a option -> 'b option
let optTest: Js.Option.t(int) = Js.Option.map(x => x, Js.Option.some(1));
我收到以下错误:
This expression should not be a function, the expected type is (. 'a) => 'b
其中 x => x
为红色。我真的很困惑,为什么 map
不起作用?从它的类型签名看来我使用它是正确的,但编译器说第一个参数不应该是一个函数?
简答 - 使用Belt.Option.map
代替:
let optTest: option(int) = Belt.Option.map(Some(1), x => x);
长答案:
Js
命名空间主要用于绑定到 JavaScript 的标准 API。虽然 Js.Option
由于历史原因被包含在此命名空间中,但 Js
命名空间中使用的约定仍然是非常薄的绑定。
您在文档中看到的回调函数类型 'a -> 'b [@bs]
和您在错误消息中看到的类型 (. 'a) => 'b
是完全相同的类型。但前者是 OCaml 的语法,而后者是 Reason 的语法,并且还加糖以减少攻击性。无论哪种方式,问题是当它期望这种奇怪的其他类型的函数时,你传递给它的是一个普通函数。
另一种奇怪的函数称为 uncurried 函数。之所以这样称呼是因为 Reason 中的 "normal" 函数是柯里化的,而 JavaScript 函数不是。因此,未柯里化的函数本质上只是一个原生 JavaScript 函数,您有时需要处理它,因为您可能会收到一个函数或需要将一个函数传递给更高阶的 JavaScript 函数,例如 Js
命名空间。
那么如何在 Reason 中创建一个未柯里化的函数呢?只需添加一个 .
,如类型:
let optTest: option(int) = Js.Option.map((.x) => x, Some(1);
或者如果你想不加糖(你不加糖,但为了完整起见):
let optTest: option(int) = Js.Option.map([@bs] x => x, Some(1);
附录:
您可能已经注意到,我已将示例中的 Js.Option.t
和 Js.Option.some
替换为 option
和 Some
。那是因为那些是实际的基元。 option
类型本质上定义为
type option('a) =
| Some('a)
| None
随处可见。
Js.Option.t('a)
(和Belt.Option.t('a)
)只是一个别名。 Js.Option.some
只是一个方便的函数,在 Belt.Option
中没有任何等价物。它们主要只是为了保持一致性,您通常应该改用实际的类型和变体构造函数。