使用shapeless通过HList将Future的tuple转换为tuple的Future

编程入门 行业动态 更新时间:2024-10-26 20:29:24
本文介绍了使用shapeless通过HList将Future的tuple转换为tuple的Future的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

是否有一种简单的方法可以将类型为 (Future[A], Future[B], Future[C], ..., Future[N]) 的元组转换为 Future[(A, B, C, ..., N)]?这假设元组中有未定义数量的元素.

Is there an easy way to convert a tuple of type (Future[A], Future[B], Future[C], ..., Future[N]) to Future[(A, B, C, ..., N)]? This assumes an undefined number of elements in the tuple.

我已经尝试将元组转换为 HList 并尝试了类似的 foldLeft 技巧和理解,就像在 Future.sequence 中所做的那样,但在处理传入折叠的类型方面没有运气.对递归函数进行了同样的尝试.但是由于缺少 HList.head、HList.tail,这段代码仍然无法编译.代码如下所示:

I've tried converting the tuple to HList and tried a similar trick of foldLeft and for comprehension as done in Future.sequence but no luck dealing with the types passed into the fold. Tried the same with recursive functions. But this code still does not compile due to missing HList.head, HList.tail. The code looks like follows:

def sequence[L <: HList](in: L)(implicit ihc: IsHCons[L]) = { val list = for (i <- in.head; j <- in.tail.head) yield HList(i, j) @tailrec def sequence2(fList: Future[HList], listF: HList): Future[HList] = { if (listF == HNil) fList else { val nextFList = for (l <- fList; e <- listF.head.asInstanceOf[Future[_]]) yield l :+ e sequence2(nextFList, listF.tail) } } sequence2(list, in.tail.tail) }

此代码应返回 Future[HList],然后我们可以使用 tupled 函数将其映射回元组.理想情况下,我们需要检查元组中的元素少于 3 个这一事实.但是让我们假设输入是一个大小为 3 或更大的 HList.

This code should return Future[HList] which we can then map back to tuple with the tupled function. Ideally we need to check for the fact we have less than 3 elements in the tuple. But lets assume the input is an HList of size 3 or larger for this exercise.

我使用的是 Shapeless 1.2.4,但由于其他依赖项而无法移动.

I'm on Shapeless 1.2.4 and can't move yet due to other dependencies.

提前致谢!

推荐答案

不知道这算不算简单",但是Dan Lien 和我正在讨论如何对 Options 就在前几天的元组进行排序,然后我针对这种情况的解决方案可以直接适用于Future(请注意,我为 Future 使用 scalaz-contrib 的 monad 实例;如果你使用的是 Scalaz 7.1没有必要):

Don't know whether this counts as "easy", but Dan Lien and I were discussing how to sequence tuples of Options just the other day, and my solution for that case can be straightforwardly adapted to work for Future (note that I'm using scalaz-contrib's monad instance for Future; if you're on Scalaz 7.1 this isn't necessary):

import scala.concurrent.{ ExecutionContext, Future } import scalaz._, Scalaz._, contrib.std.scalaFuture._ import shapeless._, ops.hlist.{ RightFolder, Tupler } // Might as well stay generic in `F` for this part. object applicativeFolder extends Poly2 { implicit def caseApplicative[A, B <: HList, F[_]](implicit app: Applicative[F] ) = at[F[A], F[B]] { (a, b) => app.ap(a)(app.map(b)(bb => (_: A) :: bb)) } } // It should be possible to make this part generic in `F` as well, // but type inference makes it tricky, so we specialize to `Future`. def sequence[T, EL <: HList, L <: HList, OL <: HList, OT](t: T)(implicit executor: ExecutionContext, gen: Generic.Aux[T, EL], eq: EL =:= L, folder: RightFolder.Aux[L, Future[HNil], applicativeFolder.type, Future[OL]], tupler: Tupler.Aux[OL, OT] ): Future[OT] = eq(gen.to(t)).foldRight(Future.successful(HNil: HNil))(applicativeFolder).map( tupler(_) )

哦,刚刚注意到您使用的是 1.2.4.必要的更改本质上是机械性的 - 应该可以使用以下内容:

Oh, just noticed that you're on 1.2.4. The necessary changes are essentially mechanical—something like the following should work:

// It should be possible to make this part generic in `F` as well, // but type inference makes it tricky, so we specialize to `Future`. def sequence[T, L <: HList, OL <: HList, OT](t: T)(implicit executor: ExecutionContext, hlister: HListerAux[T, L], folder: RightFolderAux[L, Future[HNil], applicativeFolder.type, Future[OL]], tupler: TuplerAux[OL, OT] ): Future[OT] = t.hlisted.foldRight(Future.successful(HNil: HNil))(applicativeFolder).map( tupler(_) )

它是这样工作的:

scala> import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.ExecutionContext.Implicits.global scala> val result = sequence((Future(1), Future('a))) result: scala.concurrent.Future[(Int, Symbol)] = ... scala> result.foreach(println) (1,'a)

请注意,sequence 实现">shapeless-contrib,但由于各种原因(涉及类型推断)在这种情况下很难使用.

Note that there is a sequence implementation in shapeless-contrib, but for various reasons (involving type inference) it's difficult to use in this situation.

更多推荐

使用shapeless通过HList将Future的tuple转换为tuple的Future

本文发布于:2023-11-25 03:13:05,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1628088.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:转换为   HList   shapeless   tuple   Future

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!