Как перевести Either.Right на Either.Left?

db.findUser(id).then(R.pipe(
  R.ifElse(firstTestHere, Either.Right, () => Either.Left(err)),
  R.map(R.ifElse(secondTestHere, obj => obj, () => Either.Left(err))),
  console.log
))

Если первый тест не пройдет, он вернет Either.Left, а второй не будет вызван. Это будет положить:

_Right {value: user}

Но если первый пройден, а второй нет, он станет:

_Right {value: _Left {value: err}}

Я хочу, чтобы он выводил только _Left {value: err}, как исправить код или есть какой-нибудь способ передачи справа налево?

1 ответ

Решение

Вы заметили, что map не может "сгладить" два Either экземпляры вместе. Для этого вы захотите использовать chain вместо.

db.findUser(id).then(R.pipe(
  R.ifElse(firstTestHere, Either.Right, () => Either.Left(err)),
  R.chain(R.ifElse(secondTestHere, Either.Right, () => Either.Left(err))),
  console.log
))

Эта схема составления серии вызовов для объединения в цепочку также может быть достигнута с помощью composeK / pipeK где каждая функция, которая должна быть составлена, должна иметь вид Monad m => a -> m b функция, которая производит некоторую монаду (такую ​​как Either) от заданного значения.

С помощью R.pipeK Ваш пример может быть изменен на что-то вроде:

// helper function to wrap up the `ifElse` logic
const assertThat = (predicate, error) =>
  R.ifElse(predicate, Either.Right, _ => Either.Left(error))

const result = db.findUser(id).then(R.pipeK(
  assertThat(firstTestHere, err),
  assertThat(secondTestHere, err)
));
Другие вопросы по тегам