Scala inner class typing - scala

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 Cards from the same Deck).

Is it possible to do the same thing without having the val deck declaration in Pile?
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).
Also, is it possible to do the same thing without the T declaration in shuffle()?
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:
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)
}
}
}
Test:
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
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.

Related

access private vars in tests in Scala without casting

i need your help with this Scala issue that i have.
I have a hierarchy of classes: Vehicle that has only common variables of every vehicle and then 3 subclasses: Car, Truck and MotorCycle, everyone with its own specific variables.
I am using pattern matching in an auxiliary object method to do some transformations depending of the type of vehicle:
object Transformation {
def someTransformation(vehicle:Vehicle):Vehicle = {
vehicle match {
case Car(<<<vars>>>) => Car(<<< transformed vars>>>)
case Truck(<<<vars>>>) => Truck(<<< transformed vars>>>)
case MotorCycle(<<<vars>>>) => MotorCycle(<<< transformed vars>>>)
}
}
}
my problem is when i have to test it, as i am returning a Vehicle (lets say a mixin), i have to cast every time it appears in order to access to the private vars of the vehicle involved.
I want a way to leave this code as it is and in tests access private members without casting, knowing that the vehicle i received as param is the same type as the vehicle i returned.
This can be addressed by generics?, how?
THANK YOU, i hope its understandable.
I think what you want to do is place a restriction on the return type of the function someTransformation. You want someTransformation to only return the type of vehicle that it is called on.
Here's how you can do this with context bounds:
trait Vehicle
case class Car(a: Int) extends Vehicle
case class Truck(b: Int) with Vehicle
case class MotorCycle(c: Int) with Vehicle
object Transformation {
trait Transformer[V <: Vehicle] {
def transform(v: V): V
}
implicit val carTransformer = new Transformer[Car] {
override def transform(c: Car): Car = Car(c.a + 1)
}
implicit val truckTransformer = new Transformer[Truck] {
override def transform(t: Truck): Truck = Truck(t.b + 10)
}
implicit val motorCycleTransformer = new Transformer[MotorCycle] {
override def transform(m: MotorCycle): MotorCycle = MotorCycle(m.c + 100)
}
def someTransformation[V <: Vehicle : Transformer](v: V): V = {
implicitly[Transformer[V]].transform(v)
}
}
Transformation.someTransformation(Car(1)) // results in Car(2)
Transformation.someTransformation(Truck(1)) // results in Truck(11)
Transformation.someTransformation(MotorCycle(1)) // results in MotorCycle(101)

Scala: How do I set a generic Trait?

I can't set up this generic trait whose parametrized forms can be consumed by a common class/object/method. I have tried different +|-|_ combinations :-)
Update: The first comment below shows that this can work if the Wrapper is also parametrized. Can a non-parametrized Wrapper do the job? Can an object Wrapper do the job? Can some magic combination of +|-|_ and all that give me the same desired result with a non-parametrized Wrapper or object?
case class OldStuff(name: String)
case class NewStuff(id: Int)
trait Poster[T] {
def translate(i: Int):T
}
class NewPoster extends Poster[NewStuff] {
def translate(i: Int):NewStuff = new NewStuff(3)
}
class OldPoster extends Poster[OldStuff] {
def translate(i: Int):OldStuff = new OldStuff("A" * 3)
}
val old = new OldPoster()
// so far so good
class Wrapper{
var poster: Poster[_] = null
def setter(p: Poster[_]) = {poster = p }
def prepare_input[A]( ) = {
val i: Int = 5
println(poster.translate(i))
}
}
val w= new Wrapper()
val old = new OldPoster()
w.setter(old)
scala> w.setter(old)
<console>:58: error: type mismatch;
found : OldPoster
required: Poster[_]
w.setter(old)
First, I don't see such error with Scala 2.11.
Then, would be better to avoid erasure by Poster[_]:
class Wrapper[T] {
var poster: Poster[T] = null
def setter(p: Poster[T]) = {poster = p }
def prepare_input() = {
val i: Int = 5
println(poster.translate(i))
}
}
val w= new Wrapper[OldStuff]()
val old = new OldPoster()
w.setter(old)
Finally, not using mutability would make the code more predictable against concurrency.
class Wrapper[T](poster: Poster[T]) {
def prepare_input() = {
val i: Int = 5
println(poster.translate(i))
}
}
val w = new Wrapper(new OldPoster())

Existential types in Scala

Please find below a short example which puzzles me.
I must concede that I have some difficulties to manipulate existential types in Scala.
How should I solve the type mismatch line 56 ?
proposer is OK type _$1 while proposers is of type _$1 <: Individual
Thanks in advance,
Maxime.
class Individual(n: String) {
protected val name=n
var preferred: Individual = this
override def toString(): String=name
}
class Man(n: String) extends Individual(n) { }
class Woman(n: String) extends Individual(n) { }
class Marriage(m: Man, w: Woman){
private val man=m
private val woman=w
def this(w: Woman, m: Man) = this(m,w)
override def toString(): String = man+"--"+woman
}
class Matching(){
private var list: List[Marriage] = Nil
def add(m: Marriage): Unit = { list = m ::list }
override def toString(): String= {
var s: String = ""
for (elm<-list) s=s+elm+" "
return s
}
}
object Test{
protected var male = true
def main(args: Array[String]): Unit = {
val al = new Man("Al")
val bob = new Man("Bob")
val alice = new Woman("Alice")
val barbara = new Woman("Barbara")
al.preferred = alice
bob.preferred = barbara
alice.preferred = bob
barbara.preferred = al
val men = Set(al, bob)
val women = Set(alice, barbara)
val m = new Matching()
//var proposers=women
var proposers: Set[_ <:Individual] = Set[Individual]()
if (male) proposers = men
else proposers = women
while (!proposers.isEmpty) {
for(proposer <- proposers) {
val proposer=proposers.head
if (proposer.isInstanceOf[Man])
m.add(new Marriage(
proposer.asInstanceOf[Man],
proposer.preferred.asInstanceOf[Woman]
))
else
m.add(new Marriage(
proposer.asInstanceOf[Woman],
proposer.preferred.asInstanceOf[Man]
))
proposers-=proposer//There is an error here
}
}
println(m)
}
}
This code is messy. It's poorly formatted, it mixes tabs and spaces, and it uses mutability even in the most trivial of places where a functional solution requires little thought.
This code also won't scale internationally to countries where same-sex marriage is a possibility.
Working from the top down...
I suspect you'll never want to directly instantiate an Individual, only ever a Man or a Woman. So a algebraic data type makes more sense, this is done with a sealed trait and case class subtypes.
I'll also drop the preferred property, as it can lead to circular references. Dealing with this in immutable data is beyond the level I'm willing to go in this answer.
sealed trait Individual {
def name: String
override def toString(): String=name
}
//as it's a case class, `name` becomes a val,
//which implements the abstract `def name` from the trait
case class Man(name: String) extends Individual
case class Woman(name: String) extends Individual
Marriage can also be a case class, and let's drop the clumsy duplication of class parameters into vals - it's just pointless boilerplate. This is also a good time to move the auxiliary constructor to a factory method in the companion object:
case class Marriage(man: Man, woman: Woman) {
override def toString(): String = man + "--" + woman
}
object Marriage {
def apply(w: Woman, m: Man) = new Marriage(m,w)
}
Matching is almost pointless, an entire class just to wrap a List? This kind of thing made sense in pre-Generics Java, but not any more. I'll keep it anyway (for now) so I can fix up that toString implementation, which is painfully mutable and uses return for no good reason:
case class Matching(){
private var list: List[Marriage] = Nil
def add(m: Marriage): Unit = { list ::= m }
override def toString() = list.mkString(" ")
}
Finally, the "meat" of the problem. Comments are inline, but you'll note that I don't need (or use) Matching. It's replaced in its entirety by the final println
object Test{
//better name, and a val (because it never changes)
protected val menPropose = true
def main(args: Array[String]): Unit = {
// `new` not required for case classes
val al = Man("Al")
val bob = Man("Bob")
val alice = Woman("Alice")
val barbara = Woman("Barbara")
// remember how preference was removed from `Individual`?
val mprefs = Map( al -> alice, bob -> barbara )
val fprefs = Map( alice -> bob, barbara -> al )
val men = Set(al, bob)
val women = Set(alice, barbara)
// nicely immutable, and using the returned value from if/else
val proposers = if (menPropose) men else women
// no while loop, name shadowing, or mutability.
// just a simple for-comprehension
val marriages = for(proposer <- proposers) yield {
//pattern-matching beats `isInstanceOf`... every time
proposer match {
case m: Man => Marriage(m, mprefs(m))
case f: Woman => Marriage(f, fprefs(f))
}
}
println(marriages mkString " ")
}
}
There's more that can be done here, way more. What of same-sex relationships? What if two or more people share the same preference? What if someone has no preference?
I could also encode the type of someone's preference into Individual instances. But that's getting a bit more advanced.

Scala: subclassing with factories

Let's say I've got two traits, one of them being a factory for another:
trait BaseT {
val name: String
def introduceYourself() = println("Hi, I am " +name)
// some other members ...
}
trait BaseTBuilder {
def build: BaseT
}
Now, I want to extend BaseT:
trait ExtendedT extends BaseT {
val someNewCoolField: Int
override def introduceYourself() = {
super.introduceYourself()
println(someNewCoolField)
}
// some other extra fields
Let's say I know how to initialize the new fields, but I'd like to use BaseTBuilder for initializing superclass members. Is there a possibility to create a trait that would be able to instantiate ExtendedT somehow? This approach obviously fails:
trait ExtendedTBuilder { self: TBuilder =>
def build: ExtendedT = {
val base = self.build()
val extended = base.asInstanceOf[ExtendedT] // this cannot work
extended.someNewCoolField = 4 // this cannot work either, assignment to val
extended
}
def buildDifferently: ExtendedT = {
new ExtendedT(4) // this fails, we don't know anything about constructors of ExtendedT
}
def build3: ExtendedT = {
self.build() with {someNewCoolField=5} //that would be cool, but it cannot work either
}
}
I'd like to have such a set of traits (or objects) that when someone supplies concrete implementation of BaseT and BaseTBuilder I could instantiantiate ExtendedT by writing:
val extendedBuilder = new ConcreteBaseTBuilder with ExtendedTBuilder
val e: ExtendedT = extendedBuilder.build
ExtendedT could contain a field of type BaseT, but then it would require manually proxying all the necessary methods and fields, which is in my opinion a violation of DRY principle. How to solve that?
How about create ExtendBaseT instance in your ExtendBaseTBuilder
trait ExtendBaseTBuilder { self : BaseTBuilder =>
def build: ExtendBaseT = {
new ExtendBaseT {
val someNewCoolField: Int = 3
}
}
}

ZeroC Ice "checked casts" in Scala

ZeroC Ice for Java translates every Slice interface Simple into (among other things) a proxy interface SimplePrx and a proxy SimplePrxHelper. If I have an ObjectPrx (the base interface for all proxies), I can check whether it actually has interface Simple by using a static method on SimplePrxHelper:
val obj : Ice.ObjectPrx = ...; // Get a proxy from somewhere...
val simple : SimplePrx = SimplePrxHelper.checkedCast(obj);
if (simple != null)
// Object supports the Simple interface...
else
// Object is not of type Simple...
I wanted to write a method castTo so that I could replace the second line with
val simple = castTo[SimplePrx](obj)
or
val simple = castTo[SimplePrxHelper](obj)
So far as I can see, Scala's type system is not expressive enough to allow me to define castTo. Is this correct?
Should be able to do something with implicits, along these lines:
object Casting {
trait Caster[A] {
def checkedCast(obj: ObjectPrx): Option[A]
}
def castTo[A](obj: ObjectPrx)(implicit caster: Caster[A]) =
caster.checkedCast(obj)
implicit object SimplePrxCaster extends Caster[SimplePrx] {
def checkedCast(obj: ObjectPrx) = Option(SimplePrxHelper.checkedCast(obj))
}
}
Then you just bring things into scope where you want to use them:
package my.package
import Casting._
...
def whatever(prx: ObjectPrx) {
castTo[SimplePrx](prx) foreach (_.somethingSimple())
}
...
You can get something like what you want with structural types:
def castTo[A](helper: { def checkedCast(o: Object): A })(o: Object) = {
helper.checkedCast(o)
}
class FooPrx { }
object FooPrxHelper {
def checkedCast(o: Object): FooPrx = o match {
case fp : FooPrx => fp
case _ => null
}
}
scala> val o: Object = new FooPrx
o: java.lang.Object = FooPrx#da8742
scala> val fp = castTo(FooPrxHelper)(o)
fp: FooPrx = FooPrx#da8742