Scala 类型列表上的类型级别映射
我有一个助手函数:Scala 类型列表上的类型级别映射,scala,shapeless,type-level-computation,Scala,Shapeless,Type Level Computation,我有一个助手函数: def findByType[T: ClassTag](xs: Seq[Any]) = xs.find(classTag[T].runtimeClass.isInstance).map(_.asInstanceOf[T]) 我现在使用的是: val foo = findByType[Foo](xs) val bar = findByType[Bar](xs) val baz = findByType[Baz](xs) trait Sifter[L <: HLis
def findByType[T: ClassTag](xs: Seq[Any]) =
xs.find(classTag[T].runtimeClass.isInstance).map(_.asInstanceOf[T])
我现在使用的是:
val foo = findByType[Foo](xs)
val bar = findByType[Bar](xs)
val baz = findByType[Baz](xs)
trait Sifter[L <: HList] extends DepFn1[Seq[Any]] {
type Out <: HList
}
object Sifter {
type Aux[L <: HList, Out0 <: HList] = Sifter[L] { type Out = Out0 }
implicit def emptySized: Aux[HNil, HNil] = new Sifter[HNil] {
type Out = HNil
def apply(xs: Seq[Any]) = HNil
}
implicit def otherSized[H, T <: HList, OutT <: HList](implicit
typeable: Typeable[H],
sifter: Aux[T, OutT]
): Aux[H :: T, Seq[H] :: OutT] = new Sifter[H :: T] {
type Out = Seq[H] :: OutT
def apply(xs: Seq[Any]) = xs.flatMap(typeable.cast) :: sifter(xs)
}
def sift[L <: HList](xs: Seq[Any])(implicit sifter: Sifter[L]): sifter.Out =
sifter(xs)
}
然而,这里有一些重复;我想要的是(伪代码):
我的选择是什么?我可以保持原样,但如果有什么简单的方法可以让它变干的话,我很想听一听
import scala.reflect.{ClassTag, classTag}
val List(foo, bar, baz) = List(classTag[Foo], classTag[Bar], classTag[Baz]).map(ct => findByType(xs)(ct))
当然,现在您正在丢失类型信息-
foo
,bar
和baz
都将具有类型选项[Any]
,如果您确实必须这样做,可以使它更干净、更安全:
import shapeless._
def findByType[T](xs: Seq[Any])(implicit t: Typeable[T]) =
xs.flatMap(t.cast).headOption
请注意,与您的实现不同,此实现不会对标准库的许多泛型类型给出错误答案:
scala> findByType[List[String]](Seq(List(1), List("a"), 'foo))
res3: Option[List[String]] = Some(List(a))
Vs
(不过,您仍然需要小心,因为这在用户定义的泛型上不起作用。)
它还可以让你做一些整洁的事情,比如:
val foo = findByType[Foo](xs)
val bar = findByType[Bar](xs)
val baz = findByType[Baz](xs)
trait Sifter[L <: HList] extends DepFn1[Seq[Any]] {
type Out <: HList
}
object Sifter {
type Aux[L <: HList, Out0 <: HList] = Sifter[L] { type Out = Out0 }
implicit def emptySized: Aux[HNil, HNil] = new Sifter[HNil] {
type Out = HNil
def apply(xs: Seq[Any]) = HNil
}
implicit def otherSized[H, T <: HList, OutT <: HList](implicit
typeable: Typeable[H],
sifter: Aux[T, OutT]
): Aux[H :: T, Seq[H] :: OutT] = new Sifter[H :: T] {
type Out = Seq[H] :: OutT
def apply(xs: Seq[Any]) = xs.flatMap(typeable.cast) :: sifter(xs)
}
def sift[L <: HList](xs: Seq[Any])(implicit sifter: Sifter[L]): sifter.Out =
sifter(xs)
}
这基本上是您想要的类型安全版本。关于丢失类型信息的好观点;我想特拉维斯的解决方案也能解决这个问题;为了理解筛选器示例,我必须更深入地研究依赖类型!但除此之外,这就是我所寻找的(虽然我的用例太小,无法保证额外的15行复杂性,但我会记住这一点,以备将来参考)。
scala> val myStuff: Seq[Any] = List(1, List('a', 'b'), "foo", 'bar)
myStuff: Seq[Any] = List(1, List(a, b), foo, 'bar)
scala> val myInts :: myCharLists :: myStrings :: HNil =
| Sifter.sift[Int :: List[Char] :: String :: HNil](myStuff)
myInts: Seq[Int] = List(1)
myCharLists: Seq[List[Char]] = List(List(a, b))
myStrings: Seq[String] = List(foo)