문제
다음과 같은 것이 있다고 가정합니다.
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)
}
}
.
readColumns()
API의 문제점은 제가 유형 정보를 잃는 것입니다. 즉,이 경우 :
object columnString extends Column[String] {
def read(cursor: Cursor): String = ...
}
object columnInt extends Column[Int] {
def read(cursor: Cursor): Int = ...
}
.
new ColumnReader().readColumns((columnString, columnInt))
와 같은 표현식은 Iterable[Any]
를 반환합니다.Tuple2[String, Int]
처럼 입력 한 것을 반환하고 싶지만 방법을 모릅니다.나는 컴파일러에 유용한 유형의 정보를 잃는다.
어쩌면 "Nofollow"> 엉성한 와 같은 도서관이 유용 할 수 있습니다.
Scala는 이와 같은 문제를 다루는 도구가 있습니다.
아이디어가 있습니까?
해결책
셰이프가없는 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)
. 다른 팁
타입 매개 변수를 취할 수있는 컨테이너를 사용하지 않는 경우 예를 들어, 예를 들어,서열 또는 목록?
trait Cursor {
}
trait Column[T] {
def read(cusor: Cursor): T
}
trait ColumnReader[T] {
def readColumns(columns: Seq[Column[T]], cursor: Cursor): Iterable[T] = {
for (column <- columns) yield column.read(cursor)
}
}
. 엉덩이가없는 hlist가 필요합니다
열의 수가 제한되어있는 경우에도 적용을 사용할 수도 있습니다.
trait Column[T] {
def read(c: Cursor) : Id[T]
}
object columnString extends Column[String]
{
override def read(c: Cursor): Id[String] = "hello"
}
object columnInt extends Column[Int] {
override def read(c: Cursor): Id[Int] = 3
}
type ColumnReader[T] = Reader[Cursor, T]
val readSpreadSheet1 : ColumnReader[(Int, String)] = Reader {
c =>
(columnInt.read(c) |@| columnString.read(c)) { (_,_)}
}
readSpreadSheet1(c)
.
가 발생합니다 :
res1: scalaz.Id.Id[(Int, String)] = (3,hello)
.
나는 또한 작은 독자 정의에 던져 졌으므로 행을 읽을 때 커서의 인스턴스를 통과시키는 것에 관심을 갖지 않아도됩니다.단점에서는 미리 열의 유형을 알아야하지만 HLIST를 사용할 때 이것도 사실 일 것이라고 생각합니다.
제휴하지 않습니다 StackOverflow