Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern matching on a simple Shapeless HLIST

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.

like image 442
Knows Not Much Avatar asked Apr 16 '17 18:04

Knows Not Much


People also ask

What is an HList?

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 .

What is shapeless Scala?

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.

What is HList 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]]]].


1 Answers

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)
  }
}
like image 108
flavian Avatar answered Oct 26 '22 23:10

flavian