假设我有以下内容:

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))
        }
    }
}


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

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

最佳答案

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


如果我们要强制执行一个您似乎想要的值依赖类型,则不是(例如,两个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使用简单的类型参数确定。例如,上面的方法并不能防止您将同一张卡不小心两次放入一堆。

关于scala - Scala内部类输入,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41402246/

10-09 09:20