Skip to content

Instantly share code, notes, and snippets.

@gbeaty
Last active December 18, 2015 21:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gbeaty/5846987 to your computer and use it in GitHub Desktop.
Save gbeaty/5846987 to your computer and use it in GitHub Desktop.
import shapeless._
import shapeless.Nat._
import shapeless.Record._
import shapeless.Tuples._
import shapeless.TypeOperators._
import shapeless.HList._
import shapeless.UnaryTCConstraint._
trait FilterSubs[L <: HList, U] {
type Out <: HList
def apply(l : L) : Out
}
object FilterSubs {
implicit def hlistFilterSubs[L <: HList, U, Out0 <: HList](implicit aux : FilterSubsAux[L, U, Out0]) = new FilterSubs[L, U] {
type Out = Out0
def apply(l : L) : Out0 = aux(l)
}
}
trait FilterSubsAux[L <: HList, U, Out <: HList] {
def apply(l : L) : Out
}
object FilterSubsAux {
import TypeOperators._
implicit def hlistFilterSubsHNil[L <: HList, U] = new FilterSubsAux[HNil, U, HNil] {
def apply(l : HNil) : HNil = HNil
}
implicit def hlistFilterSubs1[H <: U, L <: HList, U, Out <: HList]
(implicit aux : FilterSubsAux[L, U, Out], st: H <:< U) = new FilterSubsAux[H :: L, U, H :: Out] {
def apply(l : H :: L) : H :: Out = l.head :: aux(l.tail)
}
implicit def hlistFilterSubs2[H, L <: HList, U, Out <: HList]
(implicit aux : FilterSubsAux[L, U, Out], nst: H <:!< U) = new FilterSubsAux[H :: L, U, Out] {
def apply(l : H :: L) : Out = aux(l.tail)
}
}
object Tests {
// If you take all strings from a String :: HNil, you should get the same HList back. These shouldn't compile:
implicitly[FilterAux[String :: HNil, String, HNil]]
// implicitly[FilterSubsAux[String :: HNil, String, HNil]]
// These should compile:
trait Letter
trait A extends Letter
trait B extends Letter
trait Number
trait One extends Number
trait Two extends Number
implicitly[FilterSubsAux[A :: One :: B :: Two :: HNil, Letter, A :: B :: HNil]]
implicitly[FilterSubsAux[A :: One :: B :: Two :: HNil, Number, One :: Two :: HNil]]
implicitly[FilterSubsAux[A :: B :: HNil, Number, HNil]]
implicitly[FilterSubsAux[One :: Two :: HNil, Letter, HNil]]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment