Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid losing type information

Suppose I have something like this:

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)
   }
}

The problem of the readColumns() API is that I lose the type information, i.e., if I have this:

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

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

An expression like new ColumnReader().readColumns((columnString, columnInt)) returns Iterable[Any]. I would like to return something typed like Tuple2[String, Int], but don't know how. I lose type information useful to the compiler.

Maybe a library like Shapeless could be useful.

I'm sure Scala has some tool for dealing on problems like this.

Any ideas?

like image 720
david.perez Avatar asked Jul 29 '14 08:07

david.perez


People also ask

What prevents sensitive information from being lost or stolen?

Use encryption to prevent data theft. Ensure all sensitive information that is being transferred or emailed is encrypted. Encryption should also be installed on all company laptops, mobile devices and removable media.


2 Answers

An example using a shapeless 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)
like image 140
EECOLOR Avatar answered Oct 03 '22 04:10

EECOLOR


Why not use a container that can take type parameters, e.g. Seq or List?

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)
   }
}
like image 29
Ashalynd Avatar answered Oct 03 '22 05:10

Ashalynd