斯卡拉猫,穿越Seq

时间:2018-02-16 13:58:27

标签: scala traversal scala-cats

我知道我可以遍历operator new,new[] s

List

我可以将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

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

2 个答案:

答案 0 :(得分:4)

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

至于为什么,在(有些老的)猫issue中正在进行讨论。总结一下,你对Seq基础特征的了解不足,无法确定某些类型实例的规则。

答案 1 :(得分:0)

如果您完全确定所有SeqList的转换在您的代码中始终成功,您只需将Traverse结构从List转移到{ {1}}超过(伪)同构:

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的转换可能会严重失败(例如,如果序列是无限的)。它的作用就是来回转换ListSeq,并将所有方法调用转发给List

现在您可以使用此方法构建Traverse[List]的实例:

Traverse[Seq]

完整代码片段(使用scala 2.12.4和cats 1.0.1编译):

 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 }
 )