2016-05-03 10 views
3

次のコンパイル:型崩れ.toHListの挙動

しかし、これにはない:

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] 

} 

これは、次のエラーで失敗します。

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] 
              ^

なぜ第2のプログラムがありませんそれができないように追加することができるものはありますか?

おかげ

答えて

1

FromTraversable型クラスの要素型のためTypeableのインスタンスが必要です。 Shapelessは、これらのクラスをケースクラスに対して提供しますが、任意に定義されたクラスに対しては提供しません。あなたはしかし、かなり簡単に独自に定義することができます。

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 }]" 
    } 

そして:

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) 

もが:

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

scalacの-Xlog-implicitsオプションは、「この-そのような場合に便利ですあなたの元の非大文字クラスの試行で欠けていたものがTypeableのインスタンスであることを明らかにするでしょう。