아마 이런 식으로 쓰기 것 :
import cats.data.NonEmptyList, cats.implicits._
type Event = String
type EventHandler = Event => Either[Exception, Unit]
def fire(
e: Event,
subscribers: List[EventHandler]
): Either[NonEmptyList[Exception], Unit] =
subscribers.traverse_(_(e).toValidatedNel).toEither
을 (당신은 2.12.1에없는 것 또는 그러나 당신이 traverseU_
필요합니다 -Ypartial-unification
을 사용할 수없는 경우.)
하는 경우 호출이 동시에 발생하도록하려면 일반적으로 EitherT[Future, Exception, _]
에 도달하지만, 원하는 누적 오차를 줄 수는 없습니다. Applicative
이 직접 작성했기 때문에 ValidatedT
이 없습니다. 그래서 당신이 뭔가를 할 수 있습니다 :
import cats.Applicative
import cats.data.{ NonEmptyList, ValidatedNel }, cats.implicits._
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
type Event = String
type EventHandler = Event => Future[Either[Exception, Unit]]
def fire(
e: Event,
subscribers: List[EventHandler]
): Future[Either[NonEmptyList[Exception], Unit]] =
Applicative[Future].compose[ValidatedNel[Exception, ?]].traverse(subscribers)(
_(e).map(_.toValidatedNel)
).map(_.void.toEither)
(당신이 종류 - 프로젝터를 사용하지 않을 경우 ?
을 사용하는 대신 형 람다를 작성해야합니다.)
그리고 증명을 이 동시에 일어나고 있음을 자신에게 :
fire(
"a",
List(
s => Future { println(s"First: $s");().asRight },
s => Future { Thread.sleep(5000); println(s"Second: $s");().asRight },
s => Future { println(s"Third: $s");().asRight }
)
)
당신은 First
및 Third
즉시 볼 수 있습니다.
고맙습니다! 왜 당신은'Monoid'가 아닌'Applicative'를 써야할까요? 아마도 'Applicative'는 좀 더 일반적이고 아마 더 "관용적"이지만 "Monoid"는 나에게 더 단순 해 보입니다. 게다가'Validated'는 결국'Monoid' 인스턴스를 가지고 있습니다. 그것은 이유가 있습니다. – Michael
@Michael 그것은 맛의 문제이지만 "이 모든 요소에 대해이 작업을 수행하십시오"는 나에게 더 많은 경험을합니다. –
http://stackoverflow.com/a/19881777/521070에서 설명했듯이이 경우 "단조로운 추상화"가 아닌가요? – Michael