我正在尝试为属于“可识别”特征子类型的某些类型创建通用特征“回购”。我的计划是通过传递描述“可识别”子类型的通用TypeTag [HList]实例化“ Repo”的实现者。
如何使编译器保证在HList中传递的类型是特征“可识别”的子类型?
到目前为止,这是我得到的:
//All types in HList must extend Identifiable, how to enforce that at compile time?
trait Repo {
implicit val ltag: TypeTag[L] forSome {type L <: HList}
..
}
trait Identifiable {
..
}
case class Person(..) extends Identifiable
case class Address(..)
//This should compile
class MyRepo
(implicit val ltag: TypeTag[Person :: HNil])
extends Repo {
..
}
//This should not
class MyRepo
(implicit val ltag: TypeTag[Address :: HNil])
extends Repo {
..
}
//HList can contain an unknown number of types
我已经看到了一个似乎与之相关的问题:无形HList的内容的类型推断差异是我没有HList的实现可使用,因此不确定如何仅计算类型的上限。
HList上有一整套约束,由https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/hlistconstraints.scala提供。
您所追求的可能是LUBConstraint
。引用文档:
类型类,见证的每个元素
L
都是的子类型B
。
要使用它,您只需要提供的隐式证据即可LUBContraint[L, Identifiable]
。
例如
trait Repo[L <: HList] {
implicit val ltag: TypeTag[L]
implicit val ev: LUBConstraint[L, Identifiable]
}
trait Identifiable
case class Person(name: String) extends Identifiable
case class Address(street: String)
type P = Person :: HNil
class MyPersonRepo(implicit
val ltag: TypeTag[P],
val ev: LUBConstraint[P, Identifiable]
) extends Repo[P]
type A = Address :: HNil
class MyAddressRepo(implicit
val ltag: TypeTag[A],
val ev: LUBConstraint[A, Identifiable]
) extends Repo[A]
new MyPersonRepo // this works
new MyAddressRepo // this doesn't
如果您愿意使用抽象类而不是特征,则可以使所有内容变得更好
abstract class Repo[L <: HList](implicit
val ltag: TypeTag[L],
val ev: LUBConstraint[L, Identifiable]
)
trait Identifiable
case class Person(name: String) extends Identifiable
case class Address(street: String)
type P = Person :: HNil
class MyPersonRepo extends Repo[P]
type A = Address :: HNil
class MyAddressRepo extends Repo[A]
现在,在扩展类时,您将立即得到错误。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句