我可以使用Typeclasses获得非混合子类,共享联合收割机的实现以及返回子类类型吗?
猫和狗都是宠物,因此有一个年龄。我想定义一个选择
方法,给定两只猫或两只狗,都会选择最古老的宠物,但是当cat 和同时选择哪种宠物出现狗。
用类型的半群似乎使我在那里的90%,但我无法弄清楚是否可以定义selectOldest
一旦从理论上讲,由于所有pet
s都有一个年龄,因此不需要为每个pet
实现它仍然返回子类的类型并保留“猫和狗不混合”规则:
trait Pet {
def age: Int
// When implementation is shared, it *doesn't* return the subclass type
def _chooseOldest(rhs: Pet): Pet = if (age > rhs.age) this else rhs
}
case class Dog(age: Int) extends Pet
case class Cat(age: Int) extends Pet
trait Semigroup[A] {
def chooseOldest(lhs: A, rhs: A): A
}
// When the implementation returns the subclass type, it can't be shared
implicit val dogSemigroup = new Semigroup[Dog] {
override def chooseOldest(lhs: Dog, rhs: Dog): Dog = if (lhs.age > rhs.age) lhs else rhs
}
implicit val catSemigroup = new Semigroup[Cat] {
override def chooseOldest(lhs: Cat, rhs: Cat): Cat = if (lhs.age > rhs.age) lhs else rhs
}
def chooseGeneric[P <: Pet](p1: P, p2: P)(implicit ev: Semigroup[P]): P = ev.chooseOldest(p1, p2)
def canChooseDogs(d1: Dog, d2: Dog)(implicit ev: Semigroup[Dog]): Dog = chooseGeneric(d1, d2)(ev)
def canChooseCats(c1: Cat, c2: Cat)(implicit ev: Semigroup[Cat]): Cat = chooseGeneric(c1, c2)(ev)
// Appropriately errors because there is no Semigroup[Pet]
def cantMixCatsAndDogs(c: Cat, d: Dog)(implicit ev: Semigroup[Pet]): Pet = chooseGeneric(c, d)(ev)
如果我不知道这一点,我将尝试 f-bond-bond-bond-bond-bond-bond-typer-typermormormist 仅仅因为这是我第一次进入类型类。
是否可以使用TypeClasses实现3个给定的要求?
- 猫和狗不能“合并”
selectoldest
有一个实现- ,那里存在
selectOldest
,它返回 sublellages type
Cats and Dogs are both Pets, and thus have an age. I would like to define a chooseOldest
method that, given either two cats or two dogs, will choose whichever pet is oldest, but which will refuse to choose when both a cat and a dog are presented.
Semigroups implemented with typeclasses seems to get me 90% of the way there, but I can't figure out if it is possible to define chooseOldest
once; theoretically since all Pet
s have an age, it should not need to be implemented for each Pet
, but practically speaking I can't figure out how to define it only once while still returning the type of the subclass and retaining the "cats and dogs don't mix" rule:
trait Pet {
def age: Int
// When implementation is shared, it *doesn't* return the subclass type
def _chooseOldest(rhs: Pet): Pet = if (age > rhs.age) this else rhs
}
case class Dog(age: Int) extends Pet
case class Cat(age: Int) extends Pet
trait Semigroup[A] {
def chooseOldest(lhs: A, rhs: A): A
}
// When the implementation returns the subclass type, it can't be shared
implicit val dogSemigroup = new Semigroup[Dog] {
override def chooseOldest(lhs: Dog, rhs: Dog): Dog = if (lhs.age > rhs.age) lhs else rhs
}
implicit val catSemigroup = new Semigroup[Cat] {
override def chooseOldest(lhs: Cat, rhs: Cat): Cat = if (lhs.age > rhs.age) lhs else rhs
}
def chooseGeneric[P <: Pet](p1: P, p2: P)(implicit ev: Semigroup[P]): P = ev.chooseOldest(p1, p2)
def canChooseDogs(d1: Dog, d2: Dog)(implicit ev: Semigroup[Dog]): Dog = chooseGeneric(d1, d2)(ev)
def canChooseCats(c1: Cat, c2: Cat)(implicit ev: Semigroup[Cat]): Cat = chooseGeneric(c1, c2)(ev)
// Appropriately errors because there is no Semigroup[Pet]
def cantMixCatsAndDogs(c: Cat, d: Dog)(implicit ev: Semigroup[Pet]): Pet = chooseGeneric(c, d)(ev)
If I can't figure this out, I'll try F-bounded polymorphism next, but I suspect that there is a solution here that I'm missing simply because this is my first foray into type classes.
Is it possible to implement the 3 given requirements using typeclasses?
- Cats and dogs can't be "combined"
chooseOldest
has a single implementation- There exists a
chooseOldest
which returns the subclass type
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以做到这一点:
请注意,
notgiven [p =:= pet]
是确保不会有允许混合类型的实例。You can do this:
Note that the
NotGiven[P =:= Pet]
is what ensures that there won't be an instance that allows mixing types.