【问题标题】:Family Polymorphism in ScalaScala 中的家族多态性
【发布时间】:2013-01-03 05:53:56
【问题描述】:

目前在 Scala 中推荐的家族多态模式是什么?

在尝试游戏建模方法时,最近出现了这种解决方案:

trait Game[G <: Game[G]] {

  type PLAYER <: Player[G]
  type STATE <: State[G]

  def players(): Set[G#PLAYER]

  def startState(): G#STATE
}

trait Player[G <: Game[G]]

trait State[G <: Game[G]] {
  def player(): G#PLAYER
}

一个特定的游戏(本例中是扑克)可以用这些特征来表达,如下所示:

class Poker() extends Game[Poker] {

  type PLAYER = PokerPlayer
  type STATE = PokerState

  val p1 = new PokerPlayer()

  def players() = Set(p1)

  def startState(): PokerState = ...
}

class PokerPlayer() extends Player[Poker]

class PokerState() extends State[Poker] {
  def player(): PokerPlayer = ...
}

我对此设置有几个问题:

  1. Game[G &lt;: Game[G]]在英语中的发音是怎样的GGame 在这种情况下扮演的角色的名称是什么? (具体指这种“递归”关系。)

  2. 这是“家庭多态”的合理实现吗?在高层次上,我的理解是,这意味着 Game 及其 PLAYER 和 STATE 必须作为一个“家庭”而变化。我在其他地方看到的 Scala 中的族多态性存在很大差异,我不清楚不同的权衡:

  3. 欢迎讨论涉及类型类、宏、f 有界多态性或其他任何内容的族多态性方法。

【问题讨论】:

  • 在 Suereth 的“Scala in Depth”的清单 7.6 中,显示了具有类似约束的更高种类的 FileLike 特征。该清单用作 Typeclasses 可以做得更好的示例。 [Typeclass 替代品似乎比它取代的版本更直观,所以我认为我缺少一些基本的东西。]

标签: scala polymorphism


【解决方案1】:

我会质疑是否需要定义特征“外部”的类。 PlayerState 类型已经依赖于 Game,因此您无需尝试进一步限制它。

trait Game {
  type Player
  type State <: StateLike

  trait StateLike {
    def player: Player
  }

  def startState: State
}

class Poker extends Game {
  class Player
  class State extends StateLike { ... }
  val startState = new State
}

如果需要,您可以使用蛋糕模式将不同的部分分成不同的特征/文件。

trait PokerPlayer extends Game {
  class Player
}
trait PokerState extends Game with PokerPlayer {
  class State extends StateLike { ... }
}
class Poker extends Game with PokerPlayer with PokerState {
  val startState = ...
}

【讨论】:

  • 谢谢!是的,这似乎更加地道。我已经有一段时间没有提出这个问题了,所以我很快就会重新熟悉代码和您的解决方案。
  • 你能定义更精细的家庭类型,比如'TexasPoker',其中'Player'是'Poker.Player'的子类型吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-05-31
  • 1970-01-01
  • 1970-01-01
  • 2019-11-28
  • 2018-03-05
  • 2023-03-13
  • 2017-07-17
相关资源
最近更新 更多