Динамически параметризовать функцию Poly1 в бесформенном
У меня такая ситуация (урезанная до основных частей)
class Foo[L <: HList](columns: L) {
class toRecord(row: Row) extends Poly1 {
implicit def caseColumn[T] = at[Column[T]] { /* map to a record field */ }
}
def asRecord = {
val resultSet: Stream[Row] = // computation to get result set
resultSet.map { row =>
val m = new toRecord(row) // this can't work
columns.map(m)
}
}
}
Это не работает с map
хочет стабильный идентификатор и m
не является. Так что мне нужно как можно больше Poly1 singleton objects
столько строк у меня в наборе результатов.
Эта проблема обсуждается здесь: https://groups.google.com/forum/, но я не могу найти способ сделать эту работу.
В связанном обсуждении Майлз Сабин предложил fold
с Poly2
вместо map
с Poly1
, но я не могу понять, как использовать это предложение в моем случае.
1 ответ
Хорошо, я наконец-то смог использовать Poly2
с foldRight
для того, чтобы смоделировать параметрическую карту.
Вот пример, чтобы получить идею
object toRecord extends Poly2 {
implicit def caseColumn[A, B] = at[Column[A], (Row, B)] {
case (col, (row, acc)) =>
val field = doMyThingy(row, col) // "map" `col` to a recordField using `row` as parameter
(row, field :: acc)
}
}
def asRecord[L <: HList, O <: HList](
implicit folder: RightFolder[L, (Row, HNil.type), toRecord.type, (Row, O)]
): Stream[O] = {
val resultSet: Stream[Row] = // computation to get result set
resultSet.map { row => columns.foldRight((row, HNil))(toRecord)._2 }
}
Таким образом, "хитрость" заключается в том, чтобы передать параметр в качестве начального значения сгиба и нести его во время вычисления.
Внутри вычисления мы применяем преобразование к каждому элементу, используя row
в качестве параметра (наше "параметрическое отображение"), а затем просто добавляем его в аккумулятор.
Когда мы закончим, мы получим кортеж, содержащий row
и нанесенный на карту HList
: мы можем просто отказаться от первого (._2
) и нам пора.