Skip to content

Instantly share code, notes, and snippets.

@ramirez7
Last active September 21, 2016 04:27
Show Gist options
  • Select an option

  • Save ramirez7/5c9c2b7fab95a394f5fe31bab5e7e24c to your computer and use it in GitHub Desktop.

Select an option

Save ramirez7/5c9c2b7fab95a394f5fe31bab5e7e24c to your computer and use it in GitHub Desktop.
import shapeless._
import shapeless.record._
import shapeless.ops.hlist.Mapper
import shapeless.ops.hlist.ToTraversable
import shapeless.ops.record.{Keys, Fields}
import org.joda.time.format.DateTimeFormatter
import org.joda.time.LocalDate
object ShapelessCsv {
trait MkColumn[C] {
def apply(col: C): String
}
object MkColumn {
implicit val stringMkColumn: MkColumn[String] = new MkColumn[String] { def apply(col: String): String = col }
implicit val intMkColumn: MkColumn[Int] = new MkColumn[Int] { def apply(col: Int): String = col.toString }
implicit def optionMkColumn[A](implicit ev: MkColumn[A]): MkColumn[Option[A]] = new MkColumn[Option[A]] {
def apply(col: Option[A]): String = col.map(ev(_)).getOrElse("")
}
trait FormattedLocalDate[FMT <: DateTimeFormatter] extends Any {
def date: LocalDate
}
implicit def formattedDateMkColumn[FMT <: DateTimeFormatter, A <: FormattedLocalDate[FMT]](implicit w: Witness.Aux[FMT]): MkColumn[A] =
new MkColumn[A] {
def apply(col: A): String = w.value.print(col.date)
}
}
object toColumn extends Poly1 {
implicit def caseMkColumn[C, W](implicit mkColumn: MkColumn[C]) = at[(Symbol with W, C)]{case (h, c) => h.name -> mkColumn(c)}
}
trait MkRow[R] {
def header: Array[String]
def toRow(row: R): Map[String, String]
}
object MkRow {
def apply[R: MkRow]: MkRow[R] = implicitly[MkRow[R]]
implicit def row[R, Repr <: HList, Fs <: HList, KVs <: HList, Ks <: HList](implicit
lg: LabelledGeneric.Aux[R, Repr],
ks: Keys.Aux[Repr, Ks],
ksLub: ToTraversable.Aux[Ks, List, Symbol],
fs: Fields.Aux[Repr, Fs],
mp: Mapper.Aux[toColumn.type, Fs, KVs],
tt: ToTraversable.Aux[KVs, List, (String, String)]
): MkRow[R] = new MkRow[R] {
val header = ks().toList.map(_.toString).toArray
def toRow(row: R): Map[String, String] = lg.to(row).fields.map(toColumn).toList.toMap
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment