加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

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中存在序列实现,但由于各种原因(涉及类型推断),在这种情况下很难使用.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读