gpt4 book ai didi

scala - 基于函数的参数化类型强制参数和返回类型限制

转载 作者:行者123 更新时间:2023-12-01 13:39:58 25 4
gpt4 key购买 nike

我正在学习 Scala 对象和类型系统,作为练习,我决定实现一个赛亚人训练应用程序,一个赛亚人可以训练其他赛亚人升级。

    class Saiyan
class SuperSaiyan extends Saiyan
class SuperSaiyan2 extends SuperSaiyan
class SuperSaiyan3 extends SuperSaiyan2

trait Trainer[A <: Saiyan]{
def train(trainee: A):A
}

val noob = new Saiyan
val goku = new SuperSaiyan2 with Trainer[SuperSaiyan2] {
//needs override define of train method.
}

val trainedNoob = goku.train(noob)

Trait Trainer impelimentation 是肤浅的。我想对 train 方法进行一些限制,如下所示:

  1. SuperSaiyan2的train方法可以接受Saiyan的实例,
    SuperSaiyanSuperSaiyan2 但不是 SuperSaiyan3
  2. SuperSaiyan2 无法训练学员成为 SuperSaiyan3
  3. SuperSaiyan2 收的任何学员都不能降级。它必须始终升级或保持不变。

如果可能,我如何在这段代码中实现它?

最佳答案

免责声明:此问题在给定条件下无法解决。

具体你不能在逻辑上满足这个要求

  1. 任何 SuperSaiyan2 实例都不能训练 SuperSaiyan2
  2. SuperSaiyan3 实例可以训练SuperSayian3
  3. SuperSaiyan3SuperSaiyan2
  4. 的子类型

如您所见,由于 3.,一个 Supersayan3 实例也是一个 SuperSaiyan2 实例,因此 1.2. 矛盾

但是你可以尝试设置一些边界,使它们在类型级别抽象,但在实例级别指定

更新:

层级半解

可以用给定的术语和示例进行编译的最简单的方法是

class Saiyan {
type Level <: Saiyan
def train[T <: Saiyan](trainee: T)(implicit ev: Level <:< trainee.Level): Saiyan = Saiyan()
}

object Saiyan {
def apply() = new Saiyan {type Level = Saiyan}
}

class SuperSaiyan extends Saiyan {
type Level <: SuperSaiyan
override def train[T <: Saiyan](trainee: T)(implicit ev: Level <:< trainee.Level): SuperSaiyan = SuperSaiyan()
}

object SuperSaiyan {
def apply() = new SuperSaiyan {type Level = SuperSaiyan}
}

class SuperSaiyan2 extends SuperSaiyan {
type Level <: SuperSaiyan
override def train[T <: Saiyan](trainee: T)(implicit ev: Level <:< trainee.Level): SuperSaiyan2 = SuperSaiyan2()
}

object SuperSaiyan2 {
def apply() = new SuperSaiyan2 {type Level = SuperSaiyan2}
}

class SuperSaiyan3 extends SuperSaiyan2 {
type Level <: SuperSaiyan3
override def train[T <: Saiyan](trainee: T)(implicit ev: Level <:< trainee.Level): SuperSaiyan3 = SuperSaiyan3()
}

object SuperSaiyan3 {
def apply() = new SuperSaiyan3 {type Level = SuperSaiyan3}
}
override def train[T <: Saiyan](trainee: T)(implicit ev: UpperBound <:< trainee.UpperBound): SuperSaiyan3 = SuperSaiyan3()
}

object SuperSaiyan3 {
def apply() = new SuperSaiyan3 {type UpperBound = SuperSaiyan3}
}

此代码将成功编译如下代码

val goku = SuperSaiyan2()

goku.train(Saiyan())

但进一步

goku.train(goku.train(Saiyan()))

将失败,因为有关 type Level 的信息在 train 之后丢失了。在我的最佳方法中,在任何 training 计数之后使此类型可用会导致循环类型引用,这在当前 scala 中是非法的。

类型类

所以如果你真的想要偏序的类型级层次结构,你可以为此引入一些类型类

class CanTrain[+A, B]
trait SelfCanTrain[T] {
implicit val canTrainSelf: CanTrain[T, T] = new CanTrain
}

class Saiyan {
def train[T](trainee: T)(implicit ev: CanTrain[T, Saiyan]) = new Saiyan
}

object Saiyan extends SelfCanTrain[Saiyan]

class SuperSaiyan extends Saiyan {
def train[T](trainee: T)(implicit ev: CanTrain[T, SuperSaiyan]) = new SuperSaiyan
}

object SuperSaiyan extends SelfCanTrain[SuperSaiyan]

class SuperSaiyan2 extends SuperSaiyan {
def train[T](trainee: T)(implicit ev: CanTrain[T, SuperSaiyan2])= new SuperSaiyan2
}

object SuperSaiyan2 extends SelfCanTrain[SuperSaiyan2]

class SuperSaiyan3 extends SuperSaiyan2 {
def train[T](trainee: T)(implicit ev: CanTrain[T, SuperSaiyan3])= new SuperSaiyan3
}

object SuperSaiyan3 extends SelfCanTrain[SuperSaiyan3]

从现在开始非常具有传递性

goku.train(goku.train(goku.train(new Saiyan)))

会编译成功

关于scala - 基于函数的参数化类型强制参数和返回类型限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41142460/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com