Можно ли выполнить отображение в Scala HList

Я выполнил несколько реализаций HList. Один основан на выступлении Дэниела Спивака «Высокое волшебство в стране Скала», а другой - на основе сообщения в блоге Apocalisp. Цель заключалась в том, чтобы иметь разнородный список, который не является гетерогенным в первичном типе, а скорее в более высоком. Например:

val requests = Request[String] :: Request[Int] :: HNil

Я мог бы составить карту по всему списку, чтобы выполнить запрос и получить гетерогенный список высшего типа. Так:

requests.map(execute)

должно быть равно

String :: Int :: HNil

К сожалению, все мои попытки привели к HList of Any. Вот код недавней попытки:

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, которая использует свертку для создания нового HList, и снова она привела к HList любых типов. Будем признательны за любые советы.

29
задан Miles Sabin 28 August 2013 в 07:34
поделиться