对不同的Functors使用typelevel/cats flatTraverse

ste*_*bot 7 functional-programming scala scala-cats

我一直在尝试使用更抽象的函数式编程概念,例如来自scle的typelevel/cats的概念.

在这个特定的情况下,我试图消除map(_.flatten)遍历一些Futures 后调用的需要.

使用标准库,它看起来像这样:

def stdExample[T](things: Seq[T]): Future[Seq[T]] = {
  Future.traverse(things)(futureMaybeThings[T]).map(_.flatten)
}
def futureMaybeThings[T](thing: T): Future[Option[T]] = ???
Run Code Online (Sandbox Code Playgroud)

我尝试使用flatTraversetypelevel/cats,但我能得到的最好的是:

def catsExample[T](things: Seq[T]): Future[Seq[T]] = {
  things.toList.flatTraverse(futureMaybeThings[T](_).map(_.toList))
}
Run Code Online (Sandbox Code Playgroud)

things.toList要求获得Traversable需要调用,我可以使用那个.

由于flatTraverse需要fC => G[F[B]](其中两个CBT,GFutureFList),futureMaybeThings不匹配而不首先用所述结果map(_.toList).这最终比其他解决方案更糟糕.

它可以创建只上工作的功能FutureTraversableOnce(因为是隐式转换Option[A] => TraversableOnce[A]这样的实现可能是这样的:

def flatTraverse[A, B[_], C, M[X] <: TraversableOnceWithFlatten[X, M]](in: M[A])
                                                                (fn: A => Future[B[C]])
                                                                (implicit cbf: CanBuildFrom[M[A], B[C], M[B[C]]],
                                                                 asTraversable: B[C] => TraversableOnce[C],
                                                                 executor: ExecutionContext): Future[M[C]] = {
  Future.traverse(in)(fn).map(_.flatten)
}
Run Code Online (Sandbox Code Playgroud)

这现在符合我的要求:

def customExample[T](things: Seq[T]): Future[Seq[T]] = {
  flatTraverse(things)(futureMaybeThings[T])
}
Run Code Online (Sandbox Code Playgroud)

有没有办法用typelevel/cats实现同样的事情?

奖励:如果没有,那么这种功能的签名是什么样的?