Skip to content

Instantly share code, notes, and snippets.

@mergeconflict
Created March 24, 2012 22:24
Show Gist options
  • Save mergeconflict/2188596 to your computer and use it in GitHub Desktop.
Save mergeconflict/2188596 to your computer and use it in GitHub Desktop.
packaging and unpackaging multiple implicit conversions in an HList
object AllExamples extends App {
import shapeless._
final class All[L <: HList](val values: L) {
def apply[A](implicit selector: Selector[L, A]): A = values.select[A]
}
object All {
// package a value of type A, convertible to type B, into an HList containing just B
implicit def toAll0[A, B](a: A)(implicit a2b: A => B): All[B :: HNil] =
new All(a :: HNil)
// package a value of type A, convertible to B and some other types L, into an HList containing B and all types in L
implicit def toAll1[A, B, L <: _ :: _](a: A)(implicit a2b: A => B, a2l: A => All[L]): All[B :: L] =
new All(a :: a.values)
}
// example data
trait A { def a: String }
trait B { def b: String }
trait C { def c: String }
implicit def intA(n: Int): A = new A { def a = "a " + n.toString }
implicit def intB(n: Int): B = new B { def b = "b " + n.toString }
implicit def intC(n: Int): C = new C { def c = "c " + n.toString }
implicit def stringA(s: String): A = new A { def a = "a " + s }
implicit def stringB(s: String): B = new B { def b = "b " + s }
implicit def stringC(s: String): C = new C { def c = "c " + s }
// implicitly convert int and string values to A, B and Cs
val abcs: Seq[All[A :: B :: C :: HNil]] = Seq(1, "haha", 2, "hoho")
// unpack
for (abc <- abcs) {
println(abc[A].a)
println(abc[B].b)
println(abc[C].c)
}
}
@milessabin
Copy link

Yes, exactly that. Sorry I confused things by mentioning conversions ... I was playing around with something which tried to use a conversion from All[... T ...] to T which got bitten by exactly the same problem.

In my Pack case things are a bit different: the additional structure in the result type (due to the outer type constructor) seems to be enough to allow the inference/resolution to go through. I think having a single argument list with multiple Packs at different type constructors will probably work, but I haven't checked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment