如何避免丢失类型信息

dav*_*rez 6 scala shapeless

假设我有这样的事情:

trait Cursor {
}

trait Column[T] {
   def read(cusor: Cursor): T
}

trait ColumnReader {
   def readColumns(columns: Product[Column[_]], cursor: Cursor): Iterable[Any] = {
       for (column <- columns) yield column.read(cursor)
   }
}
Run Code Online (Sandbox Code Playgroud)

readColumns()API 的问题是我丢失了类型信息,即如果我有这个:

object columnString extends Column[String] {
   def read(cursor: Cursor): String = ...
}

object columnInt extends Column[Int] {
   def read(cursor: Cursor): Int = ...
}
Run Code Online (Sandbox Code Playgroud)

表达式如new ColumnReader().readColumns((columnString, columnInt))返回Iterable[Any].我想返回类似的东西Tuple2[String, Int],但不知道如何.我丢失了对编译器有用的类型信息.

也许像Shapeless这样的图书馆可能会有用.

我确信Scala有一些工具来处理这样的问题.

有任何想法吗?

EEC*_*LOR 4

使用无形状的示例HList

class Cursor

trait Column[T] {
  def read(cusor: Cursor): T
}

class CursorContainer(cursor: Cursor) {
  object mapper extends Poly1 {
    implicit def any[T] = at[Column[T]](_.read(cursor))
  }
}

class ColumnReader {

  def readColumns[T <: HList](columns: T, cursor: CursorContainer)(
    implicit m:Mapper[cursor.mapper.type, T]) = columns.map(cursor.mapper)
}

val columnString = new Column[String] {
  def read(cursor: Cursor): String = ???
}

val columnInt = new Column[Int] {
  def read(cursor: Cursor): Int = ???
}

val reader = new ColumnReader
val cursor =  new CursorContainer(new Cursor)
val result: String :: Int :: HNil =
  reader.readColumns(columnString :: columnInt :: HNil, cursor)
Run Code Online (Sandbox Code Playgroud)