Gab*_*lla 7 scala shapeless polymorphic-functions
我有这种情况(剥离到必要部分)
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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为map想要一个稳定的标识符,m而不是.所以我需要Poly1 singleton objects在结果集中有多少行.
这是与此处讨论的问题相同的问题:https://groups.google.com/forum/#!topic /shapeless-dev/P5DXRgnzqkY,但我无法找到使其工作的方法.
在链接的讨论中,Miles Sabin提出了folda Poly2而不是a mapwith a Poly1,但我无法想象如何在我的案例中使用这个建议.
好吧,我终于成功地使用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 }
}
Run Code Online (Sandbox Code Playgroud)
所以这里的"技巧"是将参数作为折叠的初始值传递并在计算过程中携带它.
在计算中,我们使用rowas参数(我们的"参数化映射")对每个元素应用变换,然后我们将它简单地附加到累加器.
当我们完成后,我们最终得到一个包含row和映射的元组HList:我们可以简单地丢弃前者(._2)并且我们很高兴.