Dynamically parametrize Poly1 function in shapeless

前端 未结 1 1496
醉话见心
醉话见心 2020-12-10 06:56

I have this situation (stripped down to the essential parts)

class Foo[L <: HList](columns: L) {

  class toRecord(row: Row) extends Poly1 {
    implicit          


        
相关标签:
1条回答
  • 2020-12-10 07:21

    Ok, I finally managed to use a Poly2 with a foldRight in order to simulate a parametric map.

    Here's an example to get the idea

    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 }
    }
    

    So the "trick" here is to pass the parameter as the initial value of the fold and carry it along during the computation.

    Inside the computation we apply a transformation on each element using row as parameter (our "parametric mapping") and then we simply append it to the accumulator.

    When we're done, we end up with a tuple containing row and the mapped HList: we can simply discard the former (._2) and we're good to go.

    0 讨论(0)
提交回复
热议问题