Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 从的泛型序列到保留类型的序列的泛型序列_Scala_Scala Collections_Either - Fatal编程技术网

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]]

我让它工作了,但我使用了
作为
方法的实例,我觉得这种方法在某些情况下可能会失败(我还不知道会是什么场景,因为我不太理解
可以从
解析构建)

我认为我应该使用custom
CanBuildFrom
实现它,但我希望有更简单的方法

以下是我的方法:

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的答案就是这样。如果您不接受并接受另一个答案,则没有问题。