Created
July 2, 2012 07:03
-
-
Save nafg/3031581 to your computer and use it in GitHub Desktop.
Extensible data processors
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
THE OBJECTIVE: | |
Given some Q[A] (Q might be ScalaQuery's query, A might be the first column of the table), | |
there should be a function that can return an object that has a Q[B] (B might be the first two columns | |
of the table), and a way to go from a B to an A (e.g. from (Int, String) to Int). We need to have a | |
collection of such objects (not sure if List or HList). | |
The purpose is this: | |
Suppose for instance I want to develop a very pluggable issue tracker. Its core implementation might | |
only support a ticket id and a description. Other extensions might add support for various other fields, | |
yet those fields might exist in the database on the same table. | |
Even if not, the number of queries to the database should not need to increase along with the number of | |
extensions. They should be able to enhance the query. | |
These objects would also be able to render the data. So the second might know how to render a B, (or a | |
String), while the first might be able to render only an A (or Int). | |
That's why the types need to be able to go from Q[A] to Q[B] as well as from B to A. | |
So for building up the query you go down the list of extensions, adding more to the query, and for | |
rendering you go up the list: each extension renders its data and passes the remaining (earlier) part | |
of the data up the list. | |
*/ | |
case class Item[A, B](get: A => B)(val apply: B => String => String) | |
class DataExtending[A] { | |
def hlist = | |
Item((_: A) => 73)(x => _ + " " + x) :: | |
Item((_: A) => "hello")(x => _ + " " + x) :: | |
Item((_: A) => false)(x => _ + " " + x) :: | |
HNil | |
object combine extends Poly2 { | |
implicit def x[L <: HList, B] = at[A => L, Item[A, B]]((aggFunc: A => L, item: Item[A, B]) => { a: A => item.get(a) :: aggFunc(a) }) | |
} | |
object apply extends Poly1 { | |
implicit def default[T] = at[(Item[A, T], T)]{ case (i, t) => i apply t } | |
} | |
object combine2 extends Poly2 { | |
implicit def x = at[String => String, String => String]{ _ andThen _ } | |
} | |
def run(a: A) = { | |
val items = hlist | |
type ItemA[B] = Item[A, B] | |
def m[L <: HList: *->*[ItemA]#λ](l: L) = null | |
//m(hlist) | |
val f1 = items.foldLeft((_: A) => HNil: HNil)(combine) | |
val res = f1(a) | |
val zipped = items zip res.reverse | |
val applied = zipped map apply | |
applied.foldLeft({ x: String => x })(combine2) | |
} | |
} | |
object Test extends App { | |
val de = new DataExtending[Double] | |
println(de.run(32.0)("start")) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment