【问题标题】:Scala inner class typingScala 内部类类型
【发布时间】:2017-05-15 02:37:42
【问题描述】:

假设我有以下:

class Deck[+T] {
    class Card(value: T)
    class Pile(val cards: List[Card]) {
        val deck = Deck.this
        def shuffle(shuffler: Shuffler): shuffler.shuffle(this)
    }
}

trait Shuffler {
    def shuffle[T](pile: Deck[T]#Pile): pile.type
}

object Shuffler {
    def randomShuffler(r: Random): Shuffler = new Shuffler {
        override def shuffle[T](pile: Deck[T]#Pile): pile.deck.Pile = {
            new pile.deck.Pile(r.shuffle(pile.cards))
        }
    }
}

Pile 中没有val deck 声明是否可以做同样的事情?另外,如果没有shuffle() 中的T 声明,是否可以做同样的事情?

我一直在玩诸如 pile: x.Pile forSome {val x: Deck[_]} 之类的东西,但由于打字问题,它们似乎无法编译(阅读:我没有完全理解其中的语义),并且我试图避免重写 Shuffler例如,改为使用原始列表(无论如何,我该如何表达?List[Deck[T]#Card] 并不完全存在,因为我想要来自同一个 DeckCards 列表)。

【问题讨论】:

  • 我可能不明白你在这里要做什么,但是CardPile 的定义存在于Deck 之外是否有意义?如果他们需要使用与Deck 相同的类型,您始终可以参数化Card[T]
  • class Deck[+T](val cards: Set[Card[T]]); class Card[T](value: T)
  • PileCardDeck 的内部类的部分原因是为了强制执行Cards 仅与单个Deck 实例相关联的事实。 (也就是说,将Deck 视为一个封装了Cards 的对象。)
  • 对于List 的事情,List[deck.Card] forSome { val deck: Deck[_] } 有效吗? (forSomeList 之外,因此所有元素中只有一个Deck。)

标签: scala inner-classes


【解决方案1】:

如果没有Pile 中的val deck 声明,是否可以做同样的事情?

如果我们想要强制执行一个值依赖类型,你似乎想要(例如,两个 Pile[Int] 仅在它们引用相同的卡组值时才兼容)。

另外,如果没有T 中的shuffle() 声明,是否可以做同样的事情?

您可以将类型参数移动到类型成员,这有时可以让您在它们仅在内部使用时无需指定它们。

这是一个想法:

object Pile {
  def apply(deck0: Deck): Pile { type D = deck0.type } = new Pile {
    val deck  = deck0
    type D    = deck0.type
    val cards = deck.cards.toList
  }
}
trait Pile { self =>
  type D <: Deck
  type Self = Pile { type D = self.deck.type }

  val deck : D
  def cards: List[deck.Card]

  def shuffle(shuffler: Shuffler): Self = shuffler.shuffle(this)
}

object Deck {
  def apply[A1](values: Set[A1]): Deck { type A = A1 } = new Deck {
    type A = A1
    val cards = values.map(Card(_))
  }
}
trait Deck {
  type A

  case class Card(value: A)

  def cards: Set[Card]
}

trait Shuffler {
  def shuffle(pile: Pile): pile.Self
}

 

object Shuffler {
  def randomShuffler(r: util.Random): Shuffler = new Shuffler {
    def shuffle(pile: Pile): pile.Self = new Pile {
      type D    = pile.deck.type
      val deck  = pile.deck
      val cards = r.shuffle(pile.cards)
    }
  }
}

测试:

val deck  = Deck(Set(1 to 10: _*))
val pile0 = Pile(deck)
pile0.cards
val sh    = Shuffler.randomShuffler(util.Random)
val pile1 = pile0.shuffle(sh)
pile1.cards

如您所见,强制执行值相关类型并非易事,所以问题是您是否真的需要它们,或者您可以使用A 的简单类型参数。例如,上述内容并不能防止您不小心将同一张卡片两次放入一堆。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-22
    • 1970-01-01
    • 2014-06-30
    相关资源
    最近更新 更多