我尝试以与实施here的方式不同的方式实施深度搜索。
import shapeless._
object condition extends Poly1 {
implicit def string = at[String] { x =>
if (x contains "o") Some(x)
else None
}
implicit def int = at[Int] { x =>
if (x.toString contains "0") Some(x.toString)
else None
}
}
object deepsearch extends Poly2 {
implicit def element[F <: Poly1, A, R](
implicit elementSearch: poly.Case.Aux[F, A :: HNil, Option[R]]
) = at[F, A]((f, a) => {
elementSearch(a)
})
implicit def hlistlike[F <: Poly1, A, L <: HList, R](
implicit gen: Generic.Aux[A, L]
, ds: poly.Case.Aux[this.type, F :: L :: HNil, Option[R]]
) = at[F, A] { (f, a) =>
ds(f, gen to a)
}
implicit def hnil[F <: Poly1, R]: Case.Aux[F, HNil, Option[R]] =
at[F, HNil]((_, _) =>
None: Option[R]
)
implicit def hcon[F <: Poly1, H, T <: HList, R](
implicit headSearch: Case.Aux[F, H, Option[R]],
tailSearch: Case.Aux[F, T, Option[R]]
): Case.Aux[F, H :: T, Option[R]] = at[F, H :: T]((f, l) =>
headSearch(f, l.head) orElse tailSearch(f, l.tail)
)
}
以下作品:
scala> deepsearch( condition , "1" :: "2" :: "3"::"foo" :: HNil)
res0: Option[String] = Some(foo)
scala> val tuple = (11, "1", "2", "srato",(1,2))
tuple: (Int, String, String, String, (Int, Int)) = (11,1,2,srato,(1,2))
scala> deepsearch( condition , tuple )
res0: Option[String] = Some(srato)
scala> deepsearch(condition, (111, (111, (111, (111, "zoo")))))
res0: Option[String] = Some(zoo)
scala> case class Foo(string: String)
defined class Foo
scala> deepsearch( condition , Foo("foo") )
res0: Option[String] = Some(foo)
scala> case class Bar(foo:Foo)
defined class Bar
scala> deepsearch( condition , Bar(Foo("foo")) )
res1: Option[String] = Some(foo)
但是以下没有编译:
scala> case class Baz(ss: String,int:Int)
defined class Baz
scala> deepsearch(condition,(11,Baz("foo",22)))
<console>: diverging implicit expansion for type
shapeless.poly.Case[A$A1203.this.deepsearch.type,shapeless.::
[A$A1203.this.condition.type,shapeless.::[(Int,$A1203.this.Baz),
shapeless.HNil]]] starting with method hcon in object deepsearch
deepsearch(condition,(11,Baz("foo",22)))
^
以下内容也不会使用上述相同的错误消息进行编译:
scala> deepsearch(condition ,11::"30"::Baz("foo",22)::HNil)
scala> deepsearch(condition , (111,222, (111,22, (111, (111, "zoo")))))
我见过类似Weird behavior trying to convert case classes to heterogeneous lists recursively with Shapeless的类似问题,但仍然无法弄清楚它为什么不编译。
那么如何让它编译所有案例呢?