Scala中的链接类型
我有一类对象,它们要么具有一种类型的ID,要么具有另一种类型的ID:Scala中的链接类型,scala,dependent-type,Scala,Dependent Type,我有一类对象,它们要么具有一种类型的ID,要么具有另一种类型的ID: sealed trait ItemId case class NumericId(id: Int) extends ItemId case class StringId(id: String) extends ItemId sealed trait Item { def id: ItemId } case class ItemWithNumericId(id: NumericId) extends Item case
sealed trait ItemId
case class NumericId(id: Int) extends ItemId
case class StringId(id: String) extends ItemId
sealed trait Item {
def id: ItemId
}
case class ItemWithNumericId(id: NumericId) extends Item
case class ItemWithStringId(id: StringId) extends Item
我想为某种检索项目的服务创建一个接口:
trait ItemService[IdType <: ItemId, ItemType <: Item] {
def get(id: IdType): ItemType
}
我意识到我可以将泛型类型添加到
项
类:
sealed trait ItemId
case class NumericId(id: Int) extends ItemId
case class StringId(id: String) extends ItemId
sealed trait Item[Id <: ItemId] {
def id: Id
}
case class ItemWithNumericId(id: NumericId) extends Item[NumericId]
case class ItemWithStringId(id: StringId) extends Item[StringId]
trait ItemService[IdType <: ItemId, ItemType <: Item[IdType]] {
def get(id: IdType): ItemType
}
ItemId
case类NumericId(id:Int)扩展了ItemId
case类StringId(id:String)扩展了ItemId
密封特征项[Id可能是这样的吗
trait Item {
type IdType
def id: IdType
}
trait ItemService[I <: Item] {
def get(id: I#IdType): Item
}
trait项{
类型IdType
定义id:IdType
}
trait-ItemService[I路径依赖类型是另一个答案所涵盖的一个选项,但出于灵活性的目的,在本例中,我个人将使用隐式/上下文边界
trait Proof[IdType <: ItemId, ItemType <: Item[IdType]]
trait ItemService[IdType <: ItemId, ItemType <: Item[IdType]] {
def get(id: IdType)(implicit ev: Proof[IdType, ItemType])
}
在这一点上,您并不真正关心您的服务是什么样子的,尽管f有界多态性稍后可能允许您进行超细粒度控制,因为您可以专门针对特定的实现进行隐式操作,并创建模糊的证明,在这些证明中,您希望为不打算混合在一起的内容提供编译时错误。我的做法是:
sealed trait ItemId
case class NumericId(id: Int) extends ItemId
case class StringId(id: String) extends ItemId
trait Item[A <: ItemId] {
def id: A
}
trait ItemService[A <: ItemId, B <: Item[A]] {
def get(id: A): B
}
这真的很好。ItemService
的实现有我想要的约束,它们可以用最少的样板代码声明。谢谢!
object Proof {
implicit numericProof: Proof[NumericId, ItemWithNumericId] = new Proof[NumericId, ItemWithNumericId] {}
...
}
sealed trait ItemId
case class NumericId(id: Int) extends ItemId
case class StringId(id: String) extends ItemId
trait Item[A <: ItemId] {
def id: A
}
trait ItemService[A <: ItemId, B <: Item[A]] {
def get(id: A): B
}
trait ItemService[A <: ItemId] {
def get(id: A): Item[A]
}