scala – 使用无形状通过HList将Future的元组转换为元组的Future
发布时间:2020-12-16 18:59:58 所属栏目:安全 来源:网络整理
导读:有没有一种简单的方法可以将类型元组(Future [A],Future [B],Future [C],…,Future [N])转换为Future [(A,B,C,N)]?这假定元组中的元素数量未定义. 我已经尝试将元组转换为HList并尝试了类似的foldLeft技巧和在Future.sequence中进行的理解,但没有运气处理传
有没有一种简单的方法可以将类型元组(Future [A],Future [B],Future [C],…,Future [N])转换为Future [(A,B,C,N)]?这假定元组中的元素数量未定义.
我已经尝试将元组转换为HList并尝试了类似的foldLeft技巧和在Future.sequence中进行的理解,但没有运气处理传递给折叠的类型.尝试使用递归函数.但由于缺少HList.head,HList.tail,此代码仍然无法编译.代码如下所示: 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. 我正在使用Shapeless 1.2.4并且由于其他依赖性而无法移动. 提前致谢! 解决方法
不知道这是否算“简单”,但
Dan Lien和我正在讨论如何对选项
just the other day的元组进行排序,而
my solution则可以直接适用于Future(注意我正在使用
scalaz-contrib的monad实例)未来;如果您使用的是Scalaz 7.1,则无需这样做:
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.必要的更改基本上是机械的 – 如下所示应该起作用: // It should be possible to make this part generic in `F` as well,hlister: HListerAux[T,L],folder: RightFolderAux[L,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) 请注意,在shapeless-contrib中存在序列实现,但由于各种原因(涉及类型推断),在这种情况下很难使用. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |