Skip to content

Instantly share code, notes, and snippets.

@tpolecat
Last active December 28, 2015 19:59
Show Gist options
  • Save tpolecat/7554206 to your computer and use it in GitHub Desktop.
Save tpolecat/7554206 to your computer and use it in GitHub Desktop.
Having a bit of a problem deriving implicit instances for product types.
import shapeless._
// typeclass for total number of fields (just an example)
class Width[A](val toInt: Int)
object Width {
// Get an instance
implicit def apply[A](implicit A: Width[A]) = A
// now derive for HList
implicit val fnil: Width[HNil] =
new Width[HNil](0)
implicit def fcons[H, T <: HList ](implicit H: Width[H], T: Width[T]): Width[H :: T] =
new Width[H :: T](H.toInt + T.toInt)
// and for products generally
implicit def fprod[P <: Product, L <: HList](implicit PL: Generic.Aux[P, L], L: Width[L]): Width[P] =
new Width[P](L.toInt)
}
// some instances
implicit val fooInt = new Width[Int](1)
implicit val fooStr = new Width[String](1)
Width[Int].toInt // 1
Width[Int :: String :: HNil].toInt // 2
Width[(Int, (String, String))].toInt // 3
Width[(Int, ((String, Int), String))].toInt // 4
// other products
case class Once(name: String)
case class Twice(f1: Once, f2: Once) // works as (Once, Int) for example
Width[Once].toInt // 1
Width[Twice].toInt // 2
Width[(Once, Int)].toInt // 2
Width[(Twice, Int)].toInt
// <console>:25: error: diverging implicit expansion for type Width[(Twice, Int)]
// starting with method fprod in object Width
// Width[(Twice, Int)].toInt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment