(注:從Shapeless: Trying to restrict HList elements by their type斯普利特)無形:用自己的餘積約束HList
問題2 - 自己的約束使用上積
我真正想要做的是編寫使用上積了新的約束。
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] {}
//隱VAL scpcEmptyLong2:CPConstraint [hlLong.type,CPType表] =新CPConstraint [hlLong.type,CPType表] {} //上述線將適合缺少的隱式 - 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) // should fail due to missing evidence
}
正在處理CPConstraint的隱式解析。具有'val hlLong::: [Long,HNil] = 1L :: HNil'並隱含地查找帶有隱含值的CPConstraint它cpcLong =隱式地[CPConstraint [hlLong.type,CPType]]'我試過'隱式val scpcEmptyLong1 :CPConstraint [:: [Long,HNil],CPType] = new CPConstraint [:: [Long,HNil],CPType] {}',它不適合隱式查找但隱含val scpcEmptyLong2:CPConstraint [hlLong.type, CPType] =新的CPConstraint [hlLong.type,CPType] {}'會。 - 爲什麼?有什麼不同? – sthielo
':: [Long,HNil]'<=>'長:: HNil' – Reactormonk