[英]How to transform F[Either[A, B]] to Either[F[A], F[B]]
背景知識:貓中有一個.separate
函數,它使我可以從F[Either[A, B]]
獲取元組(F[A], F[B])
。 鑒於此,可以很容易地構造Either[F[A], F[B]]
-鑒於我們可以檢查F
的空性(類人動物會這樣做嗎?)。 列表的代碼可能如下所示
val l: List[Either[_, _]] = ???
l.separate match {
case (Nil, rights) => Right(rights)
case (lefts, _) => Left(lefts)
}
但這似乎是一個更籠統的概念,但我不確定那是什么。 它看起來有點類似於.sequence
但是我們的G
有兩個孔。 也就是說,我們想要一個變換F[G[A, B]] -> G[F[A], F[B]]
。
您是否偶然知道這種概念是否存在,或者如何通過不帶pattern matching / if statements / Either.cond
貓來實現該目標?
您可以結合使用Alternative
和Traverse
來嘗試。
這種特殊情況可以從List
推廣到任意F
:
def collectErrors[A, B](xs: List[Either[A, B]]): Either[List[A], List[B]] = {
xs.traverse(_.left.map(List(_)).toValidated).toEither
}
這是我們需要使其工作的東西的購物清單:
List(_)
。 通常是Applicative[F].pure(_)
(或_.pure[F]
),因此我們需要Applicative
。 F[X]
上的Monoid
,以便可以在Validated
的左側累積錯誤。 幸運的是,有MonoidK[F[_]]
,它知道如何為任何給定X
生成Monoid[F[X]]
F[_]
必須是可遍歷的,因此我們可以從F[Validated[F[A], B]]
到Validated[F[A], F[B]]
,因此我們需要Traverse
。 有一個特質Alternative
,它是Applicative
和MonoidK
的組合。 將所有內容放在一起將為您提供:
import scala.util.Either
import cats._
import cats.syntax.either._
import cats.syntax.traverse._
import cats.syntax.applicative._
def collectErrors[F[_]: Alternative : Traverse, X, Y](xs: F[Either[X, Y]])
: Either[F[X], F[Y]] = {
implicit val mon = MonoidK[F].algebra[X]
xs.traverse(_.left.map(_.pure[F]).toValidated).toEither
}
現在,這應該適用於List
, Vector
, Chain
等。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.