2016-07-04 7 views
0

einen Typparameter gegeben, dass ein hList ist, ich mag eine HMAP mit dem typeTags des hList der Typen als Schlüssel erstellen, wie folgt aus:HMAP von hList Typ

(muss keinen typeTag sein, nur etwas, das die Art halten kann)

def createMap[L <: HList](valueFunction:...):HMap = { 
    //create an HMap with typeTags of HList elements as keys 
    //values of HMap is created with passed 'valueFunction' which is a type parameterized function creating the value. 
} 

case class Person(..) 
case class Address(..) 

def valueFunction[T] = Map[Long, T]() 

val hmap = createMap[Person :: Address :: HNil](valueFunction _) 

val personValue:Map[Long, Person] = hmap(typeTag[Person]) 
  1. Wie kann ich createMap (Signaturen, Rückgabewert und implementaion) implementieren?
  2. Wie kann ich eine gültige valueFunction angeben?
+0

eine typeTag für die hList Verwendung, ich zumindest geschafft, eine Art Informationen für jedes Element zu extrahieren: typeTag [L] .tpe.dealias.typeArgs.dropRight (1) versucht nun eine HMAP von erstellen Dies. – eirirlar

Antwort

0

Ich schaffte es, dies mit ein wenig Nachdenken zu tun. Sollte wohl etwas davon in Makros umwandeln.

import Repository._ 
    import shapeless.{HList, HMap, Id} 

    import scala.collection.mutable 
    import scala.reflect.api 
    import scala.reflect.runtime.universe._ 

    trait Repository[L <: HList] { 
     implicit val ltag: TypeTag[L] 

     implicit object TLM extends (~??>[TypeTag, Long, mutable.Map]) 

     val repos: HMap[(~??>[TypeTag, Long, mutable.Map])#λ] = { 
     val tts: List[TypeTag[_]] = ltag.tpe.dealias.typeArgs.dropRight(1).map(typeToTypeTag _) 
     tts.tail.foldLeft(HMap[(~??>[TypeTag, Long, mutable.Map])#λ](getEntry(tts.head)))(_ + getEntry(_)) 
     } 
    } 

    object Repository { 

     def getEntry[T](key: TypeTag[T]): (TypeTag[T], mutable.Map[Long, T]) = key -> mutable.Map[Long, T]() 

     //copied and modified from shapeless ~?> in HMap 
     class ~??>[K[_], K0, V[K0, _]] extends Serializable { 
     class λ[K, V] extends Serializable 
     } 

     object ~??> extends NatTRel0 { 
//not entirely sure if I need this method and/or the next one, but will keep it for now 
     implicit def rel[K[_], K0, V[K0, _]]: ~??>[K, K0, V] = new (~??>[K, K0, V]) 

     implicit def idKeyWitness[K0, V[K0, _], T](implicit rel: ~??>[Id, K0, V]): rel.λ[T, V[K0, T]] = new rel.λ[Id[T], V[K0, T]] 

     //this doesnt fit 3 type params, dont know how to port from ~?> 
     // implicit def idValueWitness[K[_], K0, T](implicit rel: ~??>[K, K0, Id]): rel.λ[K[T], T] = new rel.λ[K[T], Id[T]] 
     } 

     trait NatTRel0 { 
     implicit def witness[K[_], K0, V[K0, _], T](implicit rel: ~??>[K, K0, V]): rel.λ[K[T], V[K0, T]] = new rel.λ[K[T], V[K0, T]] 
     } 

     def typeToTypeTag[T](tpe: Type)(implicit mirror: Mirror = runtimeMirror(getClass.getClassLoader)): TypeTag[T] = 
     TypeTag(mirror, new api.TypeCreator { 
      def apply[U <: api.Universe with Singleton](m: api.Mirror[U]) = 
      if (m eq mirror) tpe.asInstanceOf[U#Type] 
      else throw new IllegalArgumentException(s"Type tag defined in $mirror cannot be migrated to other mirrors.") 
     }) 
    }