Skip to content

Instantly share code, notes, and snippets.

@calvinlfer
Created May 27, 2023 14:31
Show Gist options
  • Save calvinlfer/9253c8d849dec9c83646bc49a74f6979 to your computer and use it in GitHub Desktop.
Save calvinlfer/9253c8d849dec9c83646bc49a74f6979 to your computer and use it in GitHub Desktop.
Virgil ideas
package io.kaizensolutions.virgil.nextlevel
import io.kaizensolutions.virgil.nextlevel.nextlevel.peopleTable
object nextlevel {
sealed trait Table {
type TableTag
}
object Table {
type WithTag[Tag] = Table { type TableTag = Tag }
sealed trait Source[ColTaggerFunction[_]] extends Table {
val tableName: String
val columns: ColTaggerFunction[TableTag]
}
def make[ColType, Rest <: ColumnSet](name: String)(
columnSet: ColumnSet.Cons[ColType, Rest]
): Table.Source[columnSet.ColumnsRepr] =
columnSet.makeTable(name)
}
// Need to store Writer + Reader proof
final case class Column[ColumnType](name: String)
object Column {
def int(name: String): Column[Int] = Column(name)
def string(name: String): Column[String] = Column(name)
def double(name: String): Column[Double] = Column(name)
def long(name: String): Column[Long] = Column(name)
def uuid(name: String): Column[java.util.UUID] = Column(name)
}
final case class ColumnFromTable[ColumnType, TableTag](name: String)
sealed trait ColumnSet {
// Type level function used to tag columns to a table
type ColumnsRepr[TableTag]
// Append
def :*:[A](head: Column[A]): ColumnSet
protected def mkColumns[Tag]: ColumnsRepr[Tag]
}
object ColumnSet {
type Finish = Finish.type
case object Finish extends ColumnSet {
override type ColumnsRepr[TableTag] = Unit
override def :*:[ColType](head: Column[ColType]): Cons[ColType, Finish] = Cons(head, Finish)
override protected def mkColumns[Tag]: ColumnsRepr[Tag] = ()
}
final case class Cons[ColType, Rest <: ColumnSet](head: Column[ColType], rest: Rest) extends ColumnSet { self =>
override type ColumnsRepr[TableTag] = (ColumnFromTable[ColType, TableTag], rest.ColumnsRepr[TableTag])
override def :*:[AnotherColType](head: Column[AnotherColType]): Cons[AnotherColType, Cons[ColType, Rest]] =
Cons(head, self)
override protected def mkColumns[Tag]: ColumnsRepr[Tag] =
(ColumnFromTable[ColType, Tag](head.name), rest.mkColumns[Tag])
def makeTable(name: String): Table.Source[ColumnsRepr] =
new Table.Source[ColumnsRepr] {
override type TableTag
override val tableName: String = name
override val columns: ColumnsRepr[TableTag] = self.mkColumns[TableTag]
}
}
object :*: {
def unapply[A, B](tuple: (A, B)): Some[(A, B)] = Some(tuple)
}
}
import ColumnSet._
val peopleTable =
Table.make("people") {
Column.int("id") :*:
Column.string("first_name") :*:
Column.string("last_name") :*:
Finish
}
val (id: ColumnFromTable[Int, peopleTable.TableTag]) :*:
(firstName: ColumnFromTable[String, peopleTable.TableTag]) :*:
(lastName: ColumnFromTable[String, peopleTable.TableTag]) :*: _ =
peopleTable.columns
/**
* API
*
* val table = Table( column[String]("first_name) ~ column[Int]("age") ~
* column[String]("email) )
*
* val firstName ~ age ~ email ~ _ = table.columns
*
* Insert.into(table) .value(firstName, "John") .value(age, 42) .value(email,
* "[email protected]")
*/
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment