gpt4 book ai didi

scala - Monoid 的错误累积

转载 作者:行者123 更新时间:2023-12-04 06:36:02 26 4
gpt4 key购买 nike

假设我有一个函数列表 E => Either[Exception, Unit] 在事件 E 上调用并累积错误以返回 Either[List [异常(exception)],单位]

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

import cats.data.NonEmptyList

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

我想用 cats 实现 fire

 import cats.implicits._

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

这有道理吗?您将如何改进它?
如何更改 fire 以同时调用 subscribers

最佳答案

我可能会这样写:

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 上或在但无法使用 -Ypartial-unification,则需要 traverseU_。)

如果您希望调用同时发生,通常您会使用EitherT[Future, Exception, _],但这不会给您带来您想要的错误累积。没有 ValidatedT,但那是因为 Applicative 直接组合。所以你可以这样做:

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)

(请注意,如果您不使用 kind-projector,则需要写出类型 lambda 而不是使用 。)

并向自己证明它是同时发生的:

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

关于scala - Monoid 的错误累积,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42794230/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com