Обработка вложенных Может быть монады внутри будущего - PullRequest
0 голосов
/ 12 ноября 2018

Я все еще изучаю функциональное программирование и пытаюсь выяснить немного кудрявую проблему с Монадами.У меня есть ситуация, когда у меня есть будущее, которое делает HTTP-запрос и возвращает список значений, ради аргумента.Затем я хочу иметь возможность проверить, что в этом списке есть определенное значение, и я подумал бы, что возвращение монады Maybe здесь будет победой.Но затем, если это значение присутствует, я хочу иметь возможность сделать еще один HTTP-запрос на основе этого возвращенного значения, но он должен выполняться только в том случае, если это значение существует.Вот пример, который использует ramda-fantasy реализации Future & Maybe https://codesandbox.io/s/2xvy3m1qmy

Возможно, я все неправильно понимаю, так что если вам нужна дополнительная информация или нужно изменить что-либо из вышеперечисленного, перейдитедля этого.Просто чтобы уточнить, это будет мой рабочий процесс в псевдокоде:

  1. Сделайте запрос для всех значений
  2. значений фильтра и, возможно, найдите тот, который соответствует
  3. , если найден,сделать запрос, чтобы получить оставшиеся данные

Вот начальная попытка с комментариями, как указано выше:

import R from "ramda";
import Fantasy from "ramda-fantasy";
const Future = Fantasy.Future;
const Maybe = Fantasy.Maybe;

// make a fake HTTP request and return a list of values
// response :: Future Array String
const response = Future.of(['one', 'two', 'three'])

const maybeOrNothing = val => val ? Maybe.Just(val) : Maybe.Nothing()

// Maybe return our given value
// getVal :: String -> Maybe String
const getVal = input => response.map(R.find(R.equals(input))).map(maybeOrNothing)

// make another fake request
// let's pretend that this takes an ID and makes a fake ajax request to get teh data
// getValueData :: String -> Future
const getValueData = id => Future((reject, resolve) => {
  // fake HTTP request
  setTimeout(() => {
    resolve({
      id: id,
      foo: 'bar'
    })
  }, 100)
})

// 'one' should then run getValueData
// something isn't right here, do I need to map then chain?
getVal('one')
.chain(getValueData)
.fork(console.error, console.log)

// 'five' isn't there, so shouldn't run getValueData
// something isn't right here as getValueData still runs
// map(R.chain) works to not run getValueData but then it causes issues later on
getVal('five')
.chain(getValueData)
.fork(console.error, console.log)

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Мне удалось решить собственную проблему, частично благодаря предложению Берги. Ответ Берги выше был очень близок, но реализация была не совсем правильной. Проблема заключалась в том, что я пытался разобраться с будущим, а затем изменил его на «Возможно», поэтому я имел дело со следующим:

import R from "ramda";
import Fantasy from "ramda-fantasy";
const Future = Fantasy.Future;
const Maybe = Fantasy.Maybe;

// make a fake HTTP request and return a list of values
// response :: Future Array String
const response = Future.of(['one', 'two', 'three'])

const maybeOrNothing = val => val ? Maybe.Just(val) : Maybe.Nothing()
const maybeToFuture = m => Maybe.isNothing(m) ? Future.reject() : Future.of(m.value)

// Maybe return our given value
// getVal :: String -> Maybe String
const getVal = input => response.map(R.find(R.equals(input))).map(maybeOrNothing)

// make another fake request
// let's pretend that this takes an ID and makes a fake ajax request to get teh data
// getValueData :: String -> Future
const getValueData = id => Future((reject, resolve) => {
  // fake HTTP request
  setTimeout(() => {
    resolve({
      id: id,
      foo: 'bar'
    })
  }, 100)
})

// 'one' should then run getValueData
getVal('one')
  .chain(maybeToFuture)
  .chain(getValueData)
  .fork(console.error, console.log)

// five isn't there so getValueData doesn't run
getVal('five')
  .chain(maybeToFuture)
  .chain(getValueData)
  .fork(console.error, console.log)
0 голосов
/ 13 ноября 2018

Вы, должно быть, ищете sequence операции , которые могут превратить Maybe<Future<…>> в Future<Maybe<…>>, который вы затем можете присоединить к своему внешнему будущему.

с помощью traverse:

getVal('one')
.chain(traverse(Future.of, getValueData))
.fork(console.error, console.log)
...