我现在已经完成了几个HList的实现。其中一个是基于Daniel Spiewak的Scala之地中的高级巫术演讲,另一个是基于Apocalisp博客中的一篇文章。目标是拥有一个异构列表,其主要类型不是异构的,而是更高级的种类。例如:
val requests = Request[String] :: Request[Int] :: HNil
我可以对列表进行映射,执行请求并生成更高级别的异构列表。所以:
requests.map(execute)
应该相等。String :: Int :: HNil
可悲的是,我所有的尝试都导致了一个包含 Any 类型的 HList。以下是最近一次尝试的代码:
class Request[+Out](o:Out) {
type O = Out
def v:O = o
}
object HList {
trait Func[-Elem,Out] {
type Apply[E <: Elem] <: Out
def apply[N <: Elem](e:N):Apply[N]
}
sealed trait HList[Base] {
type Head <: Base
type Tail <: HList[Base]
type Map[Out,F <: Func[Base,Out]] <: HList[Out]
def head:Head
def tail:Tail
def ::[A <: Base](a:A):HList[Base]
def map[Out,F <: Func[Base,Out]](f:F):Map[Out,F]
}
case class HNil[Base]() extends HList[Base] {
type Head = Nothing
type Tail = Nothing
type Map[Out,F <: Func[Base,Out]] = HNil[Out]
def head = error("Head of an empty HList")
def tail = error("Head of an empty HList")
def ::[A <: Base](a:A) = HCons(a,this)
def map[Out,F <: Func[Base,Out]](f:F) = new HNil[Out]
}
case class HCons[Base,A <: Base,B <: HList[Base]](head: A, tail: B) extends HList[Base] {
type Head = A
type Tail = B
type Map[Out,F <: Func[Base,Out]] = HCons[Out,F#Apply[Head],Tail#Map[Out,F]]
def ::[C <: Base](c:C) = HCons(c,this)
def map[Out,F <: Func[Base,Out]](f:F) =
HCons(f(head),tail.map(f))
}
val :: = HCons
}
object Test extends Application {
import HList._
val HNil = new HNil[Request[_]]
val list = new Request[Int](1) :: new Request[String]("1") :: HNil
val (a :: b :: HNil) = list
val y:Request[String] = b
val results = list.map[Any,Unwrap.type](Unwrap)
val i:Int = results.head
}
import HList._
object Unwrap extends Func[Request[Any],Any] {
type Apply[I <: Request[Any]] = I#O
def apply[N <: Request[Any]](e:N) = null.asInstanceOf[Apply[N]]
}
另一种尝试是基于 Apocalisp 版本,使用 fold 创建新的 HList,但结果仍然是一个包含 Any 类型的 HList。如有建议,请指教。
default
替换为apply
来解决。 - Gabriele Petronellaimport poly._
成功获取了更高级函数的当前语法。我认为~>
运算符可能已经移动到poly
包中了? - Shon