Updating Address Settings
Here is a complete working example:
class Cursor {} trait Column[T] { def read(c: Cursor, index: Int): T } import shapeless._, ops.hlist.RightFolder object Columns { object readColumn extends Poly2 { implicit def a[A, B <: HList]: Case.Aux[ Column[A], (B, Cursor, Int), (A :: B, Cursor, Int) ] = at[Column[A], (B, Cursor, Int)] { case (col, (values, cursor, index)) => (col.read(cursor, index) :: values, cursor, index + 1) } } def readColumns[A <: HList, B <: HList](c: Cursor, columns: A)(implicit l: RightFolder.Aux[ A, (HNil, Cursor, Int), readColumn.type, (B, Cursor, Int) ] ): B = columns.foldRight((HNil: HNil, c, 0))(readColumn)._1 }
And then:
val stringColumn = new Column[String] { def read(c: Cursor, index: Int) = "foo" } val intColumn = new Column[Int] { def read(c: Cursor, index: Int) = 10 } Columns.readColumns(new Cursor, stringColumn :: intColumn :: HNil)
This compiles just fine and does what I expect from 2.0.0 and 2.1.0-RC1.
And I should have mentioned in my original answer that using HNil.type like this is not perfect - it works just fine, but explicitly dials HNil in the foldRight argument, since HNil better solution. Note that you must do one or the other, since the static type of HNil is equal to HNil.type , and RightFolder not covariant in the second argument.
Original answer
There is a very minor error in the definition of readColumn - you are returning Tuple4 , but you want to return Tuple3 . The following should work:
object readColumn extends Poly2 { implicit def a[A, B <: HList]: Case.Aux[ Column[A], (B, Cursor, Int), (A :: B, Cursor, Int) ] = at[Column[A], (B, Cursor, Int)] { case (col, (values, cursor, index)) => (col.read(cursor, index) :: values, cursor, index+1) } }
It is generally recommended that you specify an explicit return type for any implicit method for unrelated reasons related to implicit resolution, but in this case, an explicit description of the return type also quickly leads to an error.