(NOTE: Split from Shapeless: attempt to restrict HList elements to their type )
Question 2 - Own restrictions using Coproduct
What I really wanted to do was write a new constraint using Coproduct.
trait CPConstraint[L <: HList, CP <: Coproduct] extends Serializable object CPConstraint { import shapeless.ops.coproduct.Selector._ def apply[L <: HList, CP <: Coproduct](implicit cpc: CPConstraint[L, CP]): CPConstraint[L, CP] = cpc type <*<[CP <: Coproduct] = { // TODO: just invented a symbol ... what would be an appropriate one? type λ[L <: HList] = CPConstraint[L, CP] } implicit def hnilCP[HN <: HNil, CP <: Coproduct]: CPConstraint[HN, CP] = new CPConstraint[HN, CP] {} implicit def hlistCP[H, T <: HList, CP <: Coproduct](implicit ev: coproduct.Selector[CP, H], cpct: CPConstraint[T, CP]): CPConstraint[H :: T, CP] = new CPConstraint[H :: T, CP] {} } object testCPConstraint { import shapeless.ops.coproduct.Selector._ import CPConstraint._ type CPType = Long :+: String :+: CNil implicit val selLong = implicitly[Selector[CPType, Long]] implicit val selString = implicitly[Selector[CPType, String]] def acceptCP[L <: HList : <*<[CPType]#λ](l: L) = true val hlLong: ::[Long, HNil] = 1L :: HNil val hlString: ::[String, HNil] = "blabla" :: HNil val hlMixed: ::[String, ::[Long, HNil]] = "blabla" :: 1L :: HNil val hlMixedRev: ::[Long, ::[String, HNil]] = 1L :: "blabla" :: HNil val hlInvalid: ::[Double, HNil] = 1.0d :: HNil implicit val scpcEmpty: CPConstraint[HNil, CPType] = implicitly[CPConstraint[HNil, CPType]] implicit val scpcEmptyLong1: CPConstraint[::[Long,HNil], CPType] = new CPConstraint[::[Long,HNil], CPType] {}
// implicit val scpcEmptyLong2: CPConstraint [hlLong.type, CPType] = new CPConstraint [hlLong.type, CPType] {} // the above line will correspond to the missing implicit - WHY ???
implicit val cpcLong = implicitly[CPConstraint[hlLong.type, CPType]] val validEmpty = acceptCP(HNil: HNil) val validLong = acceptCP(1l :: HNil) val validMixed = acceptCP("blabla" :: 1l :: HNil) val invalid = acceptCP(1.0d :: HNil)