簡體   English   中英

如何將F [Either [A,B]]轉換為Either [F [A],F [B]]

[英]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貓來實現該目標?

您可以結合使用AlternativeTraverse來嘗試。

這種特殊情況可以從List推廣到任意F

def collectErrors[A, B](xs: List[Either[A, B]]): Either[List[A], List[B]] = {
  xs.traverse(_.left.map(List(_)).toValidated).toEither
}

這是我們需要使其工作的東西的購物清單:

  1. 我們需要某種替代List(_) 通常是Applicative[F].pure(_) (或_.pure[F] ),因此我們需要Applicative
  2. 我們需要F[X]上的Monoid ,以便可以在Validated的左側累積錯誤。 幸運的是,有MonoidK[F[_]] ,它知道如何為任何給定X生成Monoid[F[X]]
  3. F[_]必須是可遍歷的,因此我們可以從F[Validated[F[A], B]]Validated[F[A], F[B]] ,因此我們需要Traverse

有一個特質Alternative ,它是ApplicativeMonoidK的組合。 將所有內容放在一起將為您提供:

  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
  }

現在,這應該適用於ListVectorChain等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM