Мы все еще теряем контекст в некоторых монадах с Полугруппой? - PullRequest
0 голосов
/ 24 марта 2019

Я читаю книгу "Скала с кошками".Автор говорит, что Полугруппа не всегда обеспечивает поведение, которое мы ожидаем.И он показывает этот пример:

import cats.Semigroupal
import cats.instances.future._ // for Semigroupal
import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.language.higherKinds
val futurePair = Semigroupal[Future].
product(Future("Hello"), Future(123))
Await.result(futurePair, 1.second)
// res1: (String, Int) = (Hello,123)

В книге результат (Hello,123), но мы ожидали Future(Hello, 123).Как я понял, мы потеряли Future, поэтому нет ожидаемого контекста.

Я решил воспроизвести этот пример и получил такой результат:

Future(Success((Hello,123)))

Контекст на месте.Хм.Затем я попробовал этот эксперимент:

  val futurePair = Semigroupal[Future]
    .product(Future{Thread.sleep(100);"Hello"}, Future(123))
  println(futurePair)

Результат - Future(<not completed>).Как я и предполагал.

Так что я не могу понять, что не так с Future.Я получил ожидаемое поведение, и я не потерял контекст расчета.Может из-за Future начать расчет в момент создания?Но почему это проблема?

1 Ответ

0 голосов
/ 25 марта 2019

Await.result снимает Future, а не product, так что ваши ожидания соответствуют реальному поведению здесь. Он говорит, что некоторые люди могут ожидать последовательного выполнения вместо параллельного, из-за того, как ведут себя другие полугруппы, но он выбрал плохой пример кода, потому что результат его примера одинаков, независимо от того, выполняется ли он параллельно или последовательно. Лучшим примером, иллюстрирующим точку зрения автора, будет что-то вроде:

val futurePair = Semigroupal[Future].product(
  Future{Thread.sleep(750); "Hello},
  Future{Thread.sleep(750); 123}
)
Await.result(futurePair, 1.second)

Время Await.result истекло бы, если бы Futures был запущен последовательно.

...