Как использовать Js .Option.map? - PullRequest
       49

Как использовать Js .Option.map?

1 голос
/ 01 февраля 2020

Для этого кода:

  // 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 не работает? Судя по сигнатуре типа, похоже, я правильно ее использую, но компилятор говорит, что первый аргумент не должен быть функцией?

1 Ответ

2 голосов
/ 01 февраля 2020

Короткий ответ - используйте Belt.Option.map вместо:

let optTest: option(int) = Belt.Option.map(Some(1), x => x);

Длинный ответ:

The * Пространство имен 1013 * предназначено главным образом для привязки к стандартным API JavaScript. И хотя Js.Option по историческим причинам было включено в это пространство имен, соглашения, используемые в пространстве имен Js, по-прежнему очень условны для очень тонких привязок.

Тип, который вы видите для функции обратного вызова в документации, 'a -> 'b [@bs], и тип, который вы видите в сообщении об ошибке, (. 'a) => 'b, точно такого же типа. Но первый в синтаксисе OCaml, в то время как последний в синтаксисе Reason, а также подслащенный, чтобы выглядеть менее оскорбительным. В любом случае, проблема в том, что вы передаете ей обычную функцию, когда она ожидает эту странную функцию другого типа.

Эта странная функция другого типа называется функцией uncurried . Это вызвано тем, что «нормальные» функции в Reason каррируются, а функции 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. Они в основном просто для согласованности, и вы должны вместо этого использовать фактические конструкторы типов и вариантов.

...