Scala 从的泛型序列到保留类型的序列的泛型序列
我希望有一个函数,可以将Scala 从的泛型序列到保留类型的序列的泛型序列,scala,scala-collections,either,Scala,Scala Collections,Either,我希望有一个函数,可以将a,B]的任何iterable类型C[\u]转换为C[a],C[B]] 我让它工作了,但我使用了作为方法的实例,我觉得这种方法在某些情况下可能会失败(我还不知道会是什么场景,因为我不太理解可以从解析构建) 我认为我应该使用customCanBuildFrom实现它,但我希望有更简单的方法 以下是我的方法: type IterableCollection[A[_], B] = A[B] with Iterable[B] implicit class IterableEit
a,B]
的任何iterable类型C[\u]
转换为C[a],C[B]]
我让它工作了,但我使用了作为
方法的实例,我觉得这种方法在某些情况下可能会失败(我还不知道会是什么场景,因为我不太理解可以从
解析构建)
我认为我应该使用customCanBuildFrom
实现它,但我希望有更简单的方法
以下是我的方法:
type IterableCollection[A[_], B] = A[B] with Iterable[B]
implicit class IterableEither[C[_], A, B](self: IterableCollection[C, Either[A, B]]) {
def accumulate: Either[IterableCollection[C, A], IterableCollection[C, B]] = {
val failures = self.collect { case x @ Left(_) => x.value }.asInstanceOf[IterableCollection[C, A]]
if (failures.nonEmpty) Left(failures)
else Right(self.collect { case x @ Right(_) => x.value }.asInstanceOf[IterableCollection[C, B]])
}
}
我在Scala中编程已经有一段时间了,但从来没有依赖于
asInstanceOf
,因此我有点害怕将这种代码引入生产环境。你们有没有看到一种不用演员阵容就可以做到这一点的方法?这里有一个合理的通用方案,它不依赖于来代替:
import scala.language.higherKinds
object EitherAccumulatorExample {
import scala.collection.{IterableLike, TraversableOnce}
import scala.collection.generic.CanBuildFrom
implicit class EitherAccumulator[C[X] <: IterableLike[X, C[X]], A, B](wrapped: C[Either[A, B]]) {
def accumulate[CA <: TraversableOnce[_], CB](
implicit
cbfA: CanBuildFrom[C[Either[A, B]], A, CA],
cbfB: CanBuildFrom[C[Either[A, B]], B, CB]
): Either[CA, CB] = {
val failures: CA = wrapped.collect{ case x @ Left(_) => x.value }(cbfA)
if (failures.nonEmpty) Left(failures)
else {
val successes: CB = wrapped.collect { case x @ Right(_) => x.value }(cbfB)
Right(successes)
}
}
}
val example = List.empty[Either[Int, Char]]
val foo: Either[List[Int], List[Char]] = example.accumulate
val example2 = Vector.empty[Either[String, Double]]
val bar: Either[Vector[String], Vector[Double]] = example2.accumulate
}
导入scala.language.higherKinds
对象EIT累加示例{
导入scala.collection.{IterableLike,TraversableOnce}
导入scala.collection.generic.CanBuildFrom
隐式类EitherAccumulator[C[X]X.value}(cbfB)
对(成功)
}
}
}
val example=List.empty[Int,Char]]
val foo:List[Int],List[Char]]=example.accumulate
val example2=Vector.empty[字符串,双精度]]
val bar:Vector[字符串]或Vector[双精度]]=example2
}
我个人更愿意看一看,它应该有一个实例,它反过来提供了一个序列
方法,也许这就是你想要的。我想我应该用猫来试试这个,并想出了这个:
object SO {
import cats.instances.either._
import cats.instances.list._
import cats.syntax.traverse._
// type alias for the Iterable C
type C[A] = Iterable[A]
def doIt[A, B](c: C[Either[A, B]]): Either[A, C[B]] =
c.toList.sequence[Either[A, ?], B].map(_.to[C])
}
请注意,我使用的是Kind Projector,因此在cats中使用“?”,这将是一个函数,它通过验证并返回到其中一个。转换为验证的原因是序列需要应用程序实例
import cats.Traverse
import cats.data.{NonEmptyList, ValidatedNel}
import cats.implicits._
def accSequence[T[_], A, B](tab: T[Either[A, B]])(implicit T: Traverse[T]): Either[NonEmptyList[A], T[B]] =
tab.traverse[ValidatedNel[A, ?], B](_.toValidatedNel).toEither
val result: Either[NonEmptyList[Int], List[String]] = accSequence(List(Left(1), Right("A"), Left(2)))
这不只是一个序列吗
?它如何帮助获得或者[C[a],C[B]
?它似乎扔掉了几乎所有的“错误消息”在左侧的部分。你完全正确,我没有正确阅读问题,错过了。对不起。我认为纳扎里的解决方案看起来是最好的。是的-这是一个简单的解决方案,但你在结尾处有一个NEL
,谢谢;我现在想知道是否有某种方法可以通过使用类型类来实现这一点;尽管如此接受这个答案now@bottaio正如我在回答的最后一句中推测的那样,您可能想看看具有遍历的结构上的验证。Nazari Bardiuk的答案就是这样。如果您不接受并接受另一个答案,则没有问题。