Suppose I have the following:
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))
}
}
}
Is it possible to do the same thing without having the val deck
declaration in Pile
? Also, is it possible to do the same thing without the T
declaration in shuffle()
?
I had been playing around with things such as pile: x.Pile forSome {val x: Deck[_]}
, but they don't seem to compile due to typing issues (read: me not fully understanding semantics therein), and I'm trying to avoid rewriting Shuffler
to, say, work with raw lists instead (how do I express that, anyways? List[Deck[T]#Card]
is not quite there, since I want lists of Card
s from the same Deck
).
Not if we want to enforce a value dependent type, which you seem to want (e.g. two
Pile[Int]
being only compatible if they refer to the same deck value).You can move type parameters to type members, this can sometimes save you from needing to specify them when they are only internally used.
Here is an idea:
Test:
As you can see, enforcing value dependent types is not trivial, so the question is if you really need them, or you are ok with a simple type parameter for
A
. For example, the above doesn't prevent you from accidentally putting the same card twice into a pile.