Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.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_Traversal_Scala Cats - Fatal编程技术网

Scala 斯卡拉猫

Scala 斯卡拉猫,scala,traversal,scala-cats,Scala,Traversal,Scala Cats,我知道我可以遍历Lists import cats.instances.list._ import cats.syntax.traverse._ def doMagic(item: A): M[B] = ??? val list: List[A] = ??? val result: M[List[B]] = list.traverse(doMagic) 我可以将Seq来回转换为List val seq: Seq[A] = ??? val result: M[Seq[B]] = seq.toL

我知道我可以遍历
List
s

import cats.instances.list._
import cats.syntax.traverse._

def doMagic(item: A): M[B] = ???
val list: List[A] = ???
val result: M[List[B]] = list.traverse(doMagic)
我可以将
Seq
来回转换为
List

val seq: Seq[A] = ???
val result: M[Seq[B]] = seq.toList.traverse(doMagic).map(_.toSeq)
但是我也可以在没有样板的情况下遍历
Seq

val seq: Seq[A] = ???
val result: M[Seq[B]] = seq.traverse(doMagic)

或者,获取Traverse[Seq]实例的简单方法是什么?

Cats不为
Seq
提供类型类实例,因此除了自己实现它之外,您还需要进行转换

至于原因,有一个正在进行的讨论在一个(有点老)猫。总而言之,您对
Seq
底层特性了解得不够,无法确保某些TypeClass实例的法律适用


编辑:无需担心,它现在存在,请参见链接线程如果您绝对确信从所有
Seq
List
的转换在您的代码中总是成功的,您可以通过(伪)同构将
遍历
结构从
List
转移到
Seq

  def traverseFromIso[F[_], Z[_]]
    (forward: F ~> Z, inverse: Z ~> F)
    (implicit zt: Traverse[Z])
  : Traverse[F] = new Traverse[F] {
    def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) ⇒ B): B = zt.foldLeft(forward(fa), b)(f)
    def foldRight[A, B](fa: F[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
      zt.foldRight(forward(fa), lb)(f)

    def traverse[G[_], A, B]
      (fa: F[A])
      (f: (A) ⇒ G[B])
      (implicit appG: Applicative[G])
    : G[F[B]] = {
      (zt.traverse(forward(fa))(f)(appG)).map(zb => inverse(zb))
    }
  }
这实际上不是同构,因为从
Seq
List
的转换可能会严重失败(例如,如果序列是无限的)。它所做的只是将
Seq
来回转换为
List
,并将所有方法调用转发给
Traverse[List]
的方法调用

现在,您可以使用此方法构建
遍历[Seq]
的实例:

 implicit val seqTraverse: Traverse[Seq] = traverseFromIso(
   new FunctionK[Seq, List] { def apply[X](sx: Seq[X]): List[X] = sx.toList },
   new FunctionK[List, Seq] { def apply[X](lx: List[X]): Seq[X] = lx }
 )
完整代码段(使用scala 2.12.4和cats 1.0.1编译):


我想问一下,你到底为什么要一直将
Seq
包装到
List
再包装回来,而不是将所有东西都转换成
List
一次,然后再使用它?在我正在做的项目中,
Seq
到处都在使用,不知道为什么。也许我们可以用
List
来代替。
import cats._
import cats.implicits._
import cats.arrow.FunctionK
import scala.language.higherKinds

object TraverseFromIso {

  // This method can build you a `Traversable[Seq]` from
  // an `Traversable[List]` and a pair of polymorphic conversion
  // functions:

  def traverseFromIso[F[_], Z[_]]
    (forward: F ~> Z, inverse: Z ~> F)
    (implicit zt: Traverse[Z])
  : Traverse[F] = new Traverse[F] {
    def foldLeft[A, B](fa: F[A], b: B)(f: (B, A) ⇒ B): B = zt.foldLeft(forward(fa), b)(f)
    def foldRight[A, B](fa: F[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B] =
      zt.foldRight(forward(fa), lb)(f)

    def traverse[G[_], A, B]
      (fa: F[A])
      (f: (A) ⇒ G[B])
      (implicit appG: Applicative[G])
    : G[F[B]] = {
      (zt.traverse(forward(fa))(f)(appG)).map(zb => inverse(zb))
    }
  }

  // A little demo
  def main(args: Array[String]): Unit = {

    // To instantiate a `Traverse[Seq]`, we have to provide
    // two natural transformations (from List to Seq and back):

    implicit val seqTraverse: Traverse[Seq] = traverseFromIso(
      new FunctionK[Seq, List] { def apply[X](sx: Seq[X]): List[X] = sx.toList },
      new FunctionK[List, Seq] { def apply[X](lx: List[X]): Seq[X] = lx }
    )

    // do stuff with `Traversable[Seq]` here
  }
}