Reputation: 4345
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.
Upvotes: 7
Views: 1612
Reputation: 139038
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.
Upvotes: 11