在Scala中遍历

在Scala中遍历,scala,functional-programming,scala-cats,either,Scala,Functional Programming,Scala Cats,Either,我编写了以下简单代码: import cats.effect.IO import cats.instances.either._ import cats.syntax.TraverseSyntax object Test extends App with TraverseSyntax{ val e: Either[String, IO[Int]] = Right(IO(2)) e.sequence //error here } 不幸的是,它拒绝使用 Error:(25, 94) va

我编写了以下简单代码:

import cats.effect.IO
import cats.instances.either._
import cats.syntax.TraverseSyntax

object Test extends App with TraverseSyntax{
  val e: Either[String, IO[Int]] = Right(IO(2))
  e.sequence //error here
}
不幸的是,它拒绝使用

Error:(25, 94) value sequence is not a member of scala.util.Either

你能解释一下原因吗?我导入了
other
实例,其中包括
遍历[other[A,?]
。怎么了?

遍历[F]
被定义为一个类型的类型类,该类型只有一个类型参数
F[T]
Orther
type有两个类型参数,因此Scala无法将转换应用于
Traverse.Ops
,以便在使用type
Orther
定义的对象上使用Traverse语法方法

要使其可用,可以为
定义类型别名,该别名固定第一个类型参数的值,因此只有一个类型参数。然后,Scala将能够对使用此类型别名定义的变量使用遍历语法:

type StringOr[T] = Either[String, T]
val e: StringOr[IO[Int]] = Right(IO(2))
e.sequence
另一种方法是使用类型lambdas或获取类型的
遍历
实例,然后对其调用
序列
方法传递值:

val e: Either[String, IO[Int]] = Right(IO(2))

// With type lambda
Traverse[({ type L[T] = Either[String, T] })#L].sequence(e)

// With kind projector
Traverse[Either[String, ?]].sequence(e)

除了Kolmar的答案(非常彻底),我还想提出一个更简单的替代方案

自Scala 2.11.9以来,有一个编译器标志,允许它识别具有多个类型参数的类型何时应该像只有一个类型参数的类型那样工作。 我们称之为“部分统一”

启用部分统一的最简单方法是添加
sbt部分统一

如果您使用的是Scala 2.11.9或更高版本,还可以简单地添加编译器标志:

scalacOptions += "-Ypartial-unification"
然后,您的代码可以顺利编译:

import cats.effect.IO
import cats.instances.either._
import cats.syntax.TraverseSyntax

object Test extends App with TraverseSyntax {
  val e: Either[String, IO[Int]] = Right(IO(2))
  e.sequence // No more error here
} 

在最近发布的Scala 2.13中,默认情况下它现在处于启用状态,因此它应该是开箱即用的。

我也没有看到过traverse是cats还是scalaz。你到底想达到什么目的?我怀疑你是在找
.map
而不是
.traverse
@prayagupd我想执行转换
或者[String,F[Int]]
-->
F[String,Int]]
非常好。谢谢