2017-03-14 2 views
2

E 이벤트에서 호출하고 Either[List[Exception], Unit]을 반환하는 오류가 누적되는 함수 목록 E => Either[Exception, Unit]이 있다고 가정합니다.Monoid로 누적 된 오류

type EventHandler = E => Either[Exception, Unit] 

import cats.data.NonEmptyList 

def fire(
    e: Event, 
    subscribers: List[EventHandler] 
): Either[NonEmptyList[Exception], Unit] = ??? 

나는 그것이 의미가 있습니까 cats

import cats.implicits._ 

subscribers.foldMap (_ map (_.toValidatedNel)) 
      .map (.toEither) 
      .apply(e) 

fire을 구현하고 싶습니다? 어떻게 향상 시키겠습니까?
fire을 변경하여 subscribers을 동시에 호출하는 방법은 무엇입니까?

답변

6

아마 이런 식으로 쓰기 것 :

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 } 
) 
) 

당신은 FirstThird 즉시 볼 수 있습니다.

+0

고맙습니다! 왜 당신은'Monoid'가 아닌'Applicative'를 써야할까요? 아마도 'Applicative'는 좀 더 일반적이고 아마 더 "관용적"이지만 "Monoid"는 나에게 더 단순 해 보입니다. 게다가'Validated'는 결국'Monoid' 인스턴스를 가지고 있습니다. 그것은 이유가 있습니다. – Michael

+0

@Michael 그것은 맛의 문제이지만 "이 모든 요소에 대해이 작업을 수행하십시오"는 나에게 더 많은 경험을합니다. –

+0

http://stackoverflow.com/a/19881777/521070에서 설명했듯이이 경우 "단조로운 추상화"가 아닌가요? – Michael