I'm trying to use shapeless to accumulate easily objects in a type safe manner.
The problem is when I want to concat (:::
) two HList
. I'm encountering a newbie (it seems at least) problem. It misses a Prepend
implicit instance in the context.
However, looking into hlist.scala
, I can see that generic implicit def
are defined in the objects Prepend
and PrependAux
.
Adding import Prepend
and import PrependAux
manually didn't change anything (obviously...).
So here the code reduced to the minimum:
enter code here
import shapeless._
import HList._
import Prepend._
import PrependAux._
object test {
val a:HList = 1 :: 4 :: "A" :: HNil
val b:HList = "R" :: false :: HNil
val c:HList = a ::: b // <<<<<<<<<<< NEEDS A Prepend in the context
}
In the console now:
[error] test.scala:10: could not find implicit value for parameter prepend: shapeless.Prepend[shapeless.HList,shapeless.HList]
[error] val c:HList = a ::: b // this needs an implicit Prepend in the current context
What should burn my eyes?
thanks
EDIT
A little update to re-complexify a bit the real problem, because to vulgarization was to strong before.
Here is the kind of thing that I would be able to do:
case class A[L<:HList](a:L) {
def doSmth[C <:HList](c:C) = a ::: c
}
So I've not the access to the real type, only I know that they are HList s.
The up-casts to HList
are the problem here. There's almost nothing you can do with a plain old HList
(apart from adding new elements to it).
You can either provide more informative type annotations:
val a: Int :: Int :: String :: HNil = 1 :: 4 :: "A" :: HNil
val b: String :: Boolean :: HNil = "R" :: false :: HNil
val c: Int :: Int :: String :: String :: Boolean :: HNil = a ::: b
Or just let the types be inferred, which is usually much more convenient:
val a = 1 :: 4 :: "A" :: HNil
val b = "R" :: false :: HNil
val c = a ::: b
In response to your comment: you can do what you want if you make sure you've got the evidence you need (note that I've assumed that a: A
was a typo for a: L
, and that you'll need -Ydependent-method-types
for this to work):
case class A[L <: HList](a: L) {
def doSmth[C <: HList](c: C)(implicit p: Prepend[L, C]) = a ::: c
}
In general you can just look at the implicits that are necessary for the operations you're using, and then include them on your method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With