Coproduct/HList
# arrow
p
Coproduct/HList
b
I'm actually back to full reification, something starting with this:
Copy code
sealed class FrExpr<T>
data class FrInt(val param: String): FrExpr<Int>()
data class FrLong(val param: String): FrExpr<Long>()
data class FrString(val param: String): FrExpr<String>()
data class FrLit(val queryFragment: String): FrExpr<Nothing>()

interface FrAlgebra<RESTYPE, G> {
    val MG: Monad<G>
    val MB: Monoid<RESTYPE>

    fun interp(frs: List<FrExpr<*>>): Kind<G, RESTYPE>
}

class FrQueryConstructor: FrAlgebra<String, ForId> {
    override val MB = String.monoid()
    override val MG = Id.monad()

    override fun interp(frs: List<FrExpr<*>>) =
            frs.foldMapM(MG, MB) { fr -> when(fr) {
                is FrInt -> Id.just(" :${fr.param}: ")
                is FrLong -> Id.just(" :${fr.param}: ")
                is FrString -> Id.just(" :${fr.param}: ")
                is FrLit -> Id.just(fr.queryFragment)
            } }
}

fun main() {
    val x = listOf(
            FrLit("SELECT sum, cc FROM foo WHERE idx1="),
            FrInt("idx1"),
            FrLit(" AND idx2="),
            FrLong("idx2"),
            FrLit(" AND cc LIKE("),
            FrString("pattern"),
            FrLit(")")
    )

    with(FrQueryConstructor()) {
        println(interp(x))
    }
}
which yields
Copy code
Id(value=SELECT sum, cc FROM foo WHERE idx1= :idx1:  AND idx2= :idx2:  AND cc LIKE( :pattern: ))
as expected, with the idea that actual algebras would produce a query string and a program (probably eventually in
IO
) that takes typed parameters and would result in the JDBC binding when run. Does that seem like the right track to you in the absence of Shapeless/etc.?
(also add operator support to make the construction of the typed query better than
listOf(FrLit(...), FrInt(...), ...)
)
hmm, that structure makes less sense than I originally thought it would
... @#$@# I still need a Monoid over types, not data