Я пытаюсь составить монады в Scala, выполняя некоторые запросы к серверу. вот фрагмент кода, который я использую. Я стараюсь не использовать плоскую карту, насколько это возможно, только для понимания. Любые идеи? Я знаю, как использовать преобразователи монад, но не знаю, как составлять несколько монад. Может кто-нибудь мне помочь?
for {
session <- getSession(ticker) //IO[Future[Response]]
crumbF = session.flatMap(response => Future(parseCrumb(response.body)))
cookiesF = session.flatMap(response => Future(response.cookies))
crumb = Await.result(crumbF, 5 seconds) // Future[String]
cookies = Await.result(cookiesF, 5 seconds) //Future[Seq[Cookies]]
data <- getData(ticker, startDate, endDate, interval, crumb, cookies.head) // IO[Future[Response]]
stocksF = data.flatMap { response =>
import DefaultBodyReadables._
Future {
StockDf.mapDataToDf(response.body)
}
}
} yield stocksF
Вы пытаетесь составить монады, т.е. поместить одну монаду в другую, например, Future
с Option
внутри, или вы пытаетесь работать с разными монадами в одном понимании for
?
Неясно, подходит ли for
с этим кодом. Все эти присвоения и операторы Await
были бы более ясными, если бы они были записаны как обычный код. В конце концов, это всего лишь map
, вложенный в flatMap
, и, вероятно, так он выглядел бы яснее. И зачем вызывать flatMap
и оборачивать результат в Future
, а не просто вызывать map
?
Итак, несколько вещей.
Если вы запустите фьючерсы внутри a для понимания, тогда они будут работать последовательно, а не параллельно - если это ваше намерение, тогда хорошо. Если нет, то создайте их за пределами для понимания.
Вы не можете смешивать монадические контексты внутри для понимания.
// Yes
for {
a <- Some(5)
b <- Some(10)
} yield 5 * 10
// No
for {
a <- Some(5)
b <- Future(10)
} yield 5 * 10
Монады вообще не складываются. Трансформеры - это особые случаи, которые в некотором смысле сочиняют. Вы можете сложить несколько трансформаторов, чтобы составить несколько монад.