3

I'm trying to solve this problem and want to fold over an HList using a Poly2 function.

Here's a self-contained MWE (you can copy-paste this inside a REPL with shapeless 2.0 in order to reproduce the issue)

import shapeless._; import shapeless.record._

case class RowParser[T](value: T)

sealed trait ColParser[T, K <: Symbol] { val column: Witness.Aux[K] }
case class Nullable[T, K <: Symbol](column: Witness.Aux[K], parserF: String => RowParser[T]) extends ColParser[T, K]
case class NonNullable[T, K <: Symbol](column: Witness.Aux[K], parserF: String => RowParser[T]) extends ColParser[T, K]

val cols = NonNullable('col1, (_ => RowParser(42))) :: Nullable('col2, (_ => RowParser("foo"))) :: HNil

object toRecord extends Poly2 {
  implicit def colParser[C, T, K <: Symbol, LL <: HList](
    implicit ev: C <:< ColParser[T,K]
  ) = at[Tuple2[List[Int], LL], C] {
    case ((vals, rec), x) => (vals, field[K](vals.headOption) :: rec)
  }
}

cols.foldLeft((List(1,2), HNil))(toRecord)
// expected: Some(1) :: Some(1) :: HNil

I get this error:

error: diverging implicit expansion for type shapeless.ops.hlist.LeftFolder[shapeless.::[NonNullable[Int,this.T],shapeless.::[Nullable[String,this.T],shapeless.HNil]],(List[Int], shapeless.HNil.type),toRecord.type]

starting with method hnilLeftFolder in object LeftFolder cols.foldLeft((List(1,2), HNil))(toRecord)

So apparently the compiler can find multiple implicits to produce the LeftFolder foldLeft needs.

I can't figure out how to disambiguate and explicitly tell the compiler I actually want to derive a LeftFolder which uses toRecord.

Community
  • 1
  • 1
Gabriele Petronella
  • 106,943
  • 21
  • 217
  • 235
  • 1
    Not an answer but have you tried a right fold? It'd give you the output in the proper order and might be a little less touchy. – Travis Brown Aug 13 '14 at 21:04
  • @TravisBrown using a `foldRight` it says it cannot find an implicit value for parameter `folder`. – Gabriele Petronella Aug 13 '14 at 21:13
  • You'll need to swap the order of arguments in the `Poly2`? – Travis Brown Aug 13 '14 at 21:17
  • @TravisBrown, it works! Any idea on why the fold left did not? – Gabriele Petronella Aug 13 '14 at 21:36
  • No, but I think I've noticed something similar before (cases where I switched from left to right when left was inexplicably not working), and it'd be worth digging into. – Travis Brown Aug 13 '14 at 21:38
  • Ok, it's indeed something worth investigating. For the time being, thank you very much for the help! If you care turning your comment into an answer, I'll accept it, otherwise I'll post an answer myself tomorrow. – Gabriele Petronella Aug 13 '14 at 22:02
  • Since the question's about the `LeftFolder` issue I'd personally like to see it stay open until someone has an answer to that. – Travis Brown Aug 14 '14 at 03:56
  • Fair point. Anyway after looking at the code I believe the issue might come from swapping the implicits `Case2.Aux` and `LeftReducer` with `RightReducer.Aux` and `Case2` – Gabriele Petronella Aug 14 '14 at 10:35
  • @GabrielePetronella Did you manage to find the reason? I have the same issue - `reduceRight` works while `reduceLeft` fails to compile. – sp-niemand Aug 29 '17 at 16:09

0 Answers0