I wrote this simple code using the shapeless library
import shapeless.LabelledGeneric
case class Icecream(name: String, numberOfCherries: Int, inCone: Boolean)
object ShapelessRecordEx2 extends App {
val gen = LabelledGeneric[Icecream]
val hlist = gen.to(Icecream("vanilla", 2, false))
hlist match {
case h :: _ => println(h)
}
}
But doesn't even compile
Error:(12, 14) constructor cannot be instantiated to expected type;
found : scala.collection.immutable.::[B]
required: shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("numberOfCherries")],Int],shapeless.::[Boolean with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("inCone")],Boolean],shapeless.HNil]]]
case h :: _ => println(h)
This code would have been fine if I was working with a normal list.
A HList is a List where the type of every element is statically known at compile time. You may see them as "tuples on steroid". The beauty of HList compared to tuples is that you'll find all the essential List methods like take , head , tail , map , flatMap , zip , etc. plus a bunch of methods specific to HList .
shapeless is a type class and dependent type based generic programming library for Scala. It had its origins in several talks by Miles Sabin (@milessabin), given over the course of 2011, on implementing scrap your boilerplate and higher rank polymorphism in Scala.
HList is a recursive data structure. In Scala, we can write any pair type like ::[H, T] in a more ergonomic way like H :: T, so the type of our hlist is either Int :: Double :: String :: Boolean :: HNill or ::[Int, ::[Double, ::[String, ::[Boolean, HNill]]]].
You just need an import, by default scala.Predef
imports the ::
operator from scala.collection.immutable.List
.
import shapeless.LabelledGeneric
import shapeless.::
case class Icecream(name: String, numberOfCherries: Int, inCone: Boolean)
object ShapelessRecordEx2 extends App {
val gen = LabelledGeneric[Icecream]
val hlist = gen.to(Icecream("vanilla", 2, false))
hlist match {
case h :: _ => println(h)
}
}
There's another option, to import ListCompat._
.
import shapeless.HList.ListCompat._
object ShapelessRecordEx2 extends App {
val gen = LabelledGeneric[Icecream]
val hlist = gen.to(Icecream("vanilla", 2, false))
hlist match {
case h #: _ => println(h)
}
}
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