微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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实例.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐