Skip to content

Instantly share code, notes, and snippets.

@mpilquist
Created June 19, 2015 20:11
Show Gist options
  • Save mpilquist/d8197ce896eb961d206b to your computer and use it in GitHub Desktop.
Save mpilquist/d8197ce896eb961d206b to your computer and use it in GitHub Desktop.
Example of summoning an HList of type class instances with Shapeless
import shapeless._
package object ex {
implicit class TypeClassHListOps[L <: HList](val self: L) extends AnyVal {
def summon[TC[_]](implicit op: HListTypeClassSummoner[TC, L]) = op.instance
}
trait HListTypeClassSummoner[TC[_], L <: HList] {
type Out <: HList
val instance: Out
}
object HListTypeClassSummoner {
type Aux[TC[_], L <: HList, O <: HList] = HListTypeClassSummoner[TC, L] { type Out = O }
implicit def forHNil[TC[_]]: Aux[TC, HNil, HNil] = new HListTypeClassSummoner[TC, HNil] { type Out = HNil; val instance = HNil }
implicit def forHCons[TC[_], H, T <: HList, TCT <: HList](implicit
tch: TC[H],
rest: HListTypeClassSummoner.Aux[TC, T, TCT]
): Aux[TC, H :: T, TC[H] :: TCT] = new HListTypeClassSummoner[TC, H :: T] {
type Out = TC[H] :: TCT
val instance = tch :: rest.instance
}
}
// Example
trait Semigroup[A] { def op(x: A, y: A): A }
implicit val sgInt = new Semigroup[Int] { def op(x: Int, y: Int) = x + y }
implicit val sgString = new Semigroup[String] { def op(x: String, y: String) = x + y }
implicit def sgList[A] = new Semigroup[List[A]] { def op(x: List[A], y: List[A]) = x ++ y }
val xs = 1 :: "Hello" :: List(1, 2, 3) :: HNil
val tc = xs.summon[Semigroup]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment