Reputation: 25909
I am trying to use shapeless to choose the "non-empty" value from two HLists:
import shapeless.{ HNil, Poly2}
object choose extends Poly2 {
implicit def caseInt =
at[Int,Int]{
case (_,n) if n > 0 => n
case (o,_) => o
}
implicit def caseString =
at[String,String] {
case (_,n) if n.nonEmpty => n
case(o,_) => o
}
}
val g = "a" :: "" :: 0 :: HNil
val h = "" :: "a" :: 5 :: HNil
g.zip(h).map(choose)
I get an error on missing implicit mapper If I understand correctly I need to provide proof that the result of the zip is mappable but I am not sure how to do that
Upvotes: 5
Views: 187
Reputation: 108101
You are very close, but the definition of choose
is slightly wrong: map
takes a Poly1
not a Poly2
.
You're mapping over an hlist of tuples, so you need a polymorphic function taking a single argument (a tuple). What you are providing is instead a polymorphic function taking two arguments. The difference is subtle, but it's there.
Here's a version that works:
import shapeless.{ HNil, Poly1 }
object choose extends Poly1 {
implicit def caseInt =
at[(Int,Int)]{
case (_,n) if n > 0 => n
case (o,_) => o
}
implicit def caseString =
at[(String,String)] {
case (_,n) if n.nonEmpty => n
case(o,_) => o
}
}
val g = "a" :: "" :: 0 :: HNil
val h = "" :: "a" :: 5 :: HNil
g.zip(h).map(choose) // "a" :: "a" :: 5 :: HNil
As you can see what does the trick is extending Poly1
instead of Poly2
and defining the at
cases on tuples.
Upvotes: 5