scala – HList与一元约束varargs强制转换

假设我们有这个:

def join[A,B](a: A,b: B)
def join[A,B,C](a: A,b: B,c: C) // etc

基本上很多重载方法最多可以包含20个类型的参数.

然后通过在HList上强制执行一元类型约束来创建K列表,以便所有内部元素都是Task [_]类型.

class Test(L <: HList : *->*[Task]#λ](val deps : L = HNil)

是否可以将deps转换为任务[A1,A2,A3]等,其中A1,A3是HList的内部类型?

因此对于:

val hls = Task(1) :: Task("string") :: Task9(true) :: HNil

检索一个

Task[(Int,String,Boolean)]

为任意数量的论点做这个吗?我可以将任务[A],任务[B]转换为任务[A,B]任意数量的参数,只需要从HList转换为varargs或类似的.

解决方法

从Scala的角度来看,这些连接方法没有任何共同之处,只有它们的名称,所以如果没有很多样板(或自定义宏),在这种情况下使用它们是不可能的.相反,可以反复使用Twitter的Future本身的连接.您可以通过创建新类型来完成此操作:

import shapeless._

trait FutureSequence[L <: HList] extends DepFn1[L]

这个类型类将见证hlist L完全由期货组成,它将为我们提供一种方法将这些期货排序为Future [T],其中T是由每个期货内部类型组成的元组在L(* – > *给我们第一部分,但不支持第二部分,甚至任何方式完全没有第二部分).

伴侣对象完成所有有趣的工作:

import com.twitter.util.Future
import shapeless.ops.tuple.Prepend

object FutureSequence {
  type Aux[L <: HList,Out0] = FutureSequence[L] { type Out = Out0 }

  implicit def hnilFutureSequence: Aux[HNil,Future[Unit]] =
    new FutureSequence[HNil] {
      type Out = Future[Unit]
      def apply(l: HNil): Future[Unit] = Future.Unit
    }

  implicit def hconsFutureSequence[H,T <: HList,OutT](implicit
    fst: Aux[T,Future[OutT]],pre: Prepend[Tuple1[H],OutT]
  ): Aux[Future[H] :: T,Future[pre.Out]] = new FutureSequence[Future[H] :: T] {
    type Out = Future[pre.Out]

    def apply(l: Future[H] :: T): Future[pre.Out] =
      l.head.join(fst(l.tail)).map {
        case (h,t) => pre(Tuple1(h),t)
      }
  }
}

我们在这里使用归纳 – 首先我们描述如何对HNil进行排序(我们的基本情况),然后我们描述如何对Future [H] :: T进行排序,因为我们知道如何对T进行排序.

接下来,我们将定义一个方法,使其易于使用:

def sequence[L <: HList](l: L)(implicit fs: FutureSequence[L]): fs.Out = fs(l)

如果我们有一些例子:

val good = Future(1) :: Future("string") :: Future(true) :: HNil
 val bad = Future(1 / 0) :: Future("string") :: Future(true) :: HNil

我们可以对它们进

scala> import com.twitter.util.Await
import com.twitter.util.Await

scala> Await.result(sequence(good))
res0: (Int,Boolean) = (1,string,true)

scala> sequence(bad).onFailure(println)
java.lang.ArithmeticException: / by zero
res1: com.twitter.util.Future[(Int,Boolean)] = ...

您还可以在类的构造函数中或类上的特定方法中使用FutureSequence实例.

相关文章

共收录Twitter的14款开源软件,第1页Twitter的Emoji表情 Tw...
Java和Scala中关于==的区别Java:==比较两个变量本身的值,即...
本篇内容主要讲解“Scala怎么使用”,感兴趣的朋友不妨来看看...
这篇文章主要介绍“Scala是一种什么语言”,在日常操作中,相...
这篇文章主要介绍“Scala Trait怎么使用”,在日常操作中,相...
这篇文章主要介绍“Scala类型检查与模式匹配怎么使用”,在日...