2016-05-03 7 views
3

Folgende compiliert:Verhalten von unförmigen .toHList

Aber dies nicht:

object Run2 extends App { 

    import shapeless._ 
    import syntax.std.traversable._ 

    class Container[T](val x: T) 

    Seq(new Container(1), new Container("x")).toHList[Container[Int] :: Container[String] :: HNil] 

} 

es mit dem folgenden Fehler fehl:

Error:(40, 52) could not find implicit value for parameter fl: shapeless.ops.traversable.FromTraversable[shapeless.:: [com.adaje.service.table.Run2.Container[Int],shapeless.::[com.adaje.service.table.Run2.Container[String],shapeless.HNil]]] 
Seq(new Container(1), new Container("x")).toHList[Container[Int] :: Container[String] :: HNil] 
              ^

Warum funktioniert das zweite Programm nicht funktionieren und gibt es etwas, das hinzugefügt werden kann, so dass es tut?

Dank

Antwort

1

Die FromTraversable Typklasse erfordert Typeable Instanzen für die Elementtypen. Shapeless bietet diese standardmäßig für Fallklassen, aber nicht für beliebig definierte Klassen.

import shapeless._, shapeless.syntax.std.traversable._ 

class Container[T](val x: T) 

implicit def containerTypeable[A: Typeable]: Typeable[Container[A]] = 
    new Typeable[Container[A]] { 
    def cast(t: Any): Option[Container[A]] = t match { 
     case c: Container[_] => Typeable[A].cast(c.x).map(new Container(_)) 
     case _ => None 
    } 

    def describe: String = s"Container[${ Typeable[A].describe }]" 
    } 

Und dann: Sie können Ihre eigene ziemlich leicht, obwohl definieren

scala> val cs = Seq(new Container(1), new Container("x")) 
cs: Seq[Container[_ >: String with Int]] = List([email protected], [email protected]) 

scala> cs.toHList[Container[Int] :: Container[String] :: HNil] 
res0: Option[shapeless.::[Container[Int],shapeless.::[Container[String],shapeless.HNil]]] = Some([email protected] :: [email protected] :: HNil) 

Und auch:

scala> cs.reverse.toHList[Container[Int] :: Container[String] :: HNil] 
res1: Option[shapeless.::[Container[Int],shapeless.::[Container[String],shapeless.HNil]]] = None 

der scalac -Xlog-implicits Option kann in Fällen wie diesen-es praktisch sein‘ Ich werde klarstellen, dass das, was in Ihrem ursprünglichen nicht-klassenbasierten Versuch fehlte, die Typeable Instanzen waren.