Scala: How do I set a generic Trait? - scala

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

Related

Scala reflect string to singleton object

I'm looking for a way to convert a Scala singleton object given as a string (for example: package1.Main) to the actual instance of Main, so that I can invoke methods on it.
Example of the problem:
package x {
object Main extends App {
val objectPath: String = io.StdIn.readLine("Give an object: ") // user enters: x.B
// how to convert the objectPath (String) to a variable that references singleton B?
val b1: A = magicallyConvert1(objectPath)
b1.hi()
val b2: B.type = magicallyConvert2(objectPath)
b2.extra()
}
trait A {
def hi() = {}
}
object B extends A {
def extra() = {}
}
}
How can the magicallyConvert1 and magicallyConvert2 functions be implemented?
For a normal class, this can be done using something like:
val b: A = Class.forName("x.B").newInstance().asInstanceOf[A]
But I found a solution for singletons, using Java reflections:
A singleton is accesible in Java under the name:
package.SingletonName$.MODULE$
So you have to append "$.MODULE$", which is a static field.
So we can use standard Java reflections to get it.
So the solution is:
def magicallyConvert1(objectPath: String) = {
val clz = Class.forName(objectPath + "$")
val field = clz.getField("MODULE$")
val b: A = field.get(null).asInstanceOf[A]
b
}
def magicallyConvert2(objectPath: String) = {
val clz = Class.forName(objectPath + "$")
val field = clz.getField("MODULE$")
val b: B.type = field.get(null).asInstanceOf[B.type]
b
}
But it would be interesting to still see a solution with Scala-Reflect en Scala-Meta.
take a look at scalameta http://scalameta.org it does what you want and more

Scala inner class typing

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.

Scala Reflection Conundrum: Can you explain these weird results?

I wrote some Scala code, using reflection, that returns all vals in an object that are of a certain type. Below are three versions of this code. One of them works but is ugly. Two attempts to improve it don't work, in very different ways. Can you explain why?
First, the code:
import scala.reflect.runtime._
import scala.util.Try
trait ScopeBase[T] {
// this version tries to generalize the type. The only difference
// from the working version is [T] instead of [String]
def enumerateBase[S: universe.TypeTag]: Seq[T] = {
val mirror = currentMirror.reflect(this)
universe.typeOf[S].decls.map {
decl => Try(mirror.reflectField(decl.asMethod).get.asInstanceOf[T])
}.filter(_.isSuccess).map(_.get).filter(_ != null).toSeq
}
}
trait ScopeString extends ScopeBase[String] {
// This version works but requires passing the val type
// (String, in this example) explicitly. I don't want to
// duplicate the code for different val types.
def enumerate[S: universe.TypeTag]: Seq[String] = {
val mirror = currentMirror.reflect(this)
universe.typeOf[S].decls.map {
decl => Try(mirror.reflectField(decl.asMethod).get.asInstanceOf[String])
}.filter(_.isSuccess).map(_.get).filter(_ != null).toSeq
}
// This version tries to avoid passing the object's type
// as the [S] type parameter. After all, the method is called
// on the object itself; so why pass the type?
def enumerateThis: Seq[String] = {
val mirror = currentMirror.reflect(this)
universe.typeOf[this.type].decls.map {
decl => Try(mirror.reflectField(decl.asMethod).get.asInstanceOf[String])
}.filter(_.isSuccess).map(_.get).filter(_ != null).toSeq
}
}
// The working example
object Test1 extends ScopeString {
val IntField: Int = 13
val StringField: String = "test"
lazy val fields = enumerate[Test1.type]
}
// This shows how the attempt to generalize the type doesn't work
object Test2 extends ScopeString {
val IntField: Int = 13
val StringField: String = "test"
lazy val fields = enumerateBase[Test2.type]
}
// This shows how the attempt to drop the object's type doesn't work
object Test3 extends ScopeString {
val IntField: Int = 13
val StringField: String = "test"
lazy val fields = enumerateThis
}
val test1 = Test1.fields // List(test)
val test2 = Test2.fields // List(13, test)
val test3 = Test3.fields // List()
The "enumerate" method does work. However, as you can see from the Test1 example, it requires passing the object's own type (Test1.type) as a parameter, which should not have been necessary. The "enumerateThis" method tries to avoid that but fails, producing an empty list. The "enumerateBase" method attempts to generalize the "enumerate" code by passing the val type as a parameter. But it fails, too, producing the list of all vals, not just those of a certain type.
Any idea what's going on?
Your problem in your generic implementation is the loss of the type information of T. Also, don't use exceptions as your primary method of control logic (it's very slow!). Here's a working version of your base.
abstract class ScopeBase[T : universe.TypeTag, S <: ScopeBase[T, S] : universe.TypeTag : scala.reflect.ClassTag] {
self: S =>
def enumerateBase: Seq[T] = {
val mirror = currentMirror.reflect(this)
universe.typeOf[S].baseClasses.map(_.asType.toType).flatMap(
_.decls
.filter(_.typeSignature.resultType <:< universe.typeOf[T])
.filter(_.isMethod)
.map(_.asMethod)
.filter(_.isAccessor)
.map(decl => mirror.reflectMethod(decl).apply().asInstanceOf[T])
.filter(_ != null)
).toSeq
}
}
trait Inherit {
val StringField2: String = "test2"
}
class Test1 extends ScopeBase[String, Test1] with Inherit {
val IntField: Int = 13
val StringField: String = "test"
lazy val fields = enumerateBase
}
object Test extends App {
println(new Test1().fields)
}
Instead of getting the type from universe.typeOf you can use the runtime class currentMirror.classSymbol(getClass).toType, below is an example that works:
def enumerateThis: Seq[String] = {
val mirror = currentMirror.reflect(this)
currentMirror.classSymbol(getClass).toType.decls.map {
decl => Try(mirror.reflectField(decl.asMethod).get.asInstanceOf[String])
}.filter(_.isSuccess).map(_.get).filter(_ != null).toSeq
}
//prints List(test)
With everyone's help, here's the final version that works:
import scala.reflect.runtime.{currentMirror, universe}
abstract class ScopeBase[T: universe.TypeTag] {
lazy val enumerate: Seq[T] = {
val mirror = currentMirror.reflect(this)
currentMirror.classSymbol(getClass).baseClasses.map(_.asType.toType).flatMap {
_.decls
.filter(_.typeSignature.resultType <:< universe.typeOf[T])
.filter(_.isMethod)
.map(_.asMethod)
.filterNot(_.isConstructor)
.filter(_.paramLists.size == 0)
.map(decl => mirror.reflectField(decl.asMethod).get.asInstanceOf[T])
.filter(_ != null).toSeq
}
}
}
trait FieldScope extends ScopeBase[Field[_]]
trait DbFieldScope extends ScopeBase[DbField[_, _]] {
// etc....
}
As you see from the last few lines, my use cases are limited to scope objects for specific field types. This is why I want to parameterize the scope container. If I wanted to enumerate the fields of multiple types in a single scope container, then I would have parameterized the enumerate method.

Access type member of an extension of an abstract class in Scala

I've got an abstract class in scala:
abstract class Agent {
type geneType
val genome: Array[geneType]
implicit def geneTag: reflect.ClassTag[geneType]
def copy(newGenome: Array[geneType]): AgentT[geneType]
}
object Agent { type AgentT[A] = Agent { type geneType = A }}
I've also got an extension of that class:
case class Prisoner(initGenome: Array[Boolean]) extends Agent {
type geneType = Boolean
val genome = initGenome
def geneTag = implicitly[reflect.ClassTag[Boolean]]
def copy(newGenome: Array[geneType], memSize:Int):AgentT[Boolean] = new Prisoner(newGenome:Array[Boolean], memSize: Int)
}
I'd like to define a function that is parametrized by the geneType of an extension of Agent. I'm not sure how to access that type member of the class, though. Say it's the following function:
def slice[A](parentA: AgentT[A], parentB: AgentT[A]): (AgentT[A], AgentT[A]) = {
val genomeSize = parentA.genome.length
require (parentB.genome.length == genomeSize)
import parentA.geneTag
val index = (math.random * genomeSize + 0.5).toInt
val (aInit, aTail) = parentA.genome.splitAt(index)
val (bInit, bTail) = parentB.genome.splitAt(index)
val genomeA = Array.concat(aInit, bTail)
val genomeB = Array.concat(bInit, aTail)
(parentA.copy(genomeA), parentB.copy(genomeB))
}
Furthermore, say that this function is being called from within some other process, like this one:
abstract class Simulation[E <: Agent](population: Array[E]) {
var pop = population
// HERE's WHERE I'm CONFUSED
val (child1, child2) = slice[ ????????? ](pop(1), pop(2))
}
I was trying stuff like E.geneTag and E.geneType, and those didn't work. If I have an object of type Prisoner, I can access its geneType, Boolean, with
val pris = new Prisoner(genome, memSize)
pris.geneTag
But I'd like to access the geneTag associated with a type that extends Agent.
I'd like to figure out how to do something like Prisoner.geneTag.
Any ideas?
You were close with E.geneType. You need a type projection here, written E#geneType.
See this other SO question about type projections in general: What does the `#` operator mean in Scala?

Define function for extension of abstract class

I'm having trouble with type mismatches when trying to write a function that takes as input (and output) an object that extends an abstract class.
Here is my abstract class:
abstract class Agent {
type geneType
var genome: Array[geneType]
}
Here is my function:
def slice[T <: Agent](parentA: T, parentB: T):(T, T) = {
val genomeSize = parentA.genome.length
// Initialize children as identical to parents at first.
val childA = parentA
val childB = parentB
// the value 'index' is sampled randomly between 0 and
// the length of the genome, less 1.
// This code omitted for simplicity.
val index;
val pAslice1 = parentA.genome.slice(0, index + 1)
val pBslice1 = parentB.genome.slice(index + 1, genomeSize)
val genomeA = Array.concat(pAslice1, pBslice1)
childA.genome = genomeA
// And similary for childB.
// ...
// ...
return (childA, childB)
}
I'm receiving an error (I'm running this with sbt, by the way) as follows:
[error] .......... type mismatch;
[error] found : Array[parentA.geneType]
[error] required: Array[T#geneType]
I'm not sure what the problem is, as I'm new to abstract classes, generic type parametrization, and probably other relevant concepts whose names I don't know.
In your construction it is well possible that parentA and parentB are different types, T only gives you an upper bound (they must be at least as specific as T). Arrays are invariant in their element type, thus you cannot exchange the elements in a sound way here.
A second problem with your code is that you are returning objects of type T, but actually you are mutating the input arguments. Either you want mutation, then declare the method's return type Unit to make that clear; or create new instances of T and make Agent immutable. It depends on your performance requirements, but I would always try the immutable variant first, because it is easier to reason about.
Here is mutable variant. Note that because arrays are special objects on the JVM (no type erasure happening), you need to provide a so-called class-tag for them as well:
abstract class Agent {
type geneType
var genome: Array[geneType]
implicit def geneTag: reflect.ClassTag[geneType]
}
def slice[A](parentA: Agent { type geneType = A },
parentB: Agent { type geneType = A }): Unit = {
val genomeSize = parentA.genome.length
require (parentB.genome.length == genomeSize)
import parentA.geneTag
val index = (math.random * genomeSize + 0.5).toInt
val (aInit, aTail) = parentA.genome.splitAt(index)
val (bInit, bTail) = parentB.genome.splitAt(index)
val genomeA = Array.concat(aInit, bTail)
val genomeB = Array.concat(bInit, aTail)
parentA.genome = genomeA
parentB.genome = genomeB
}
Here you require that parentA and parentB share an exactly defined gene-type A. You can define a type alias to simplify specifying that type:
type AgentT[A] = Agent { type geneType = A }
def slice[A](parentA: AgentT[A], parentB: AgentT[A]): Unit = ...
To preserve the parents and create new children, the easiest would be to add a copy method to the Agent class:
abstract class Agent {
type geneType
var genome: Array[geneType]
implicit def geneTag: reflect.ClassTag[geneType]
def copy(newGenome: Array[geneType]): AgentT[geneType]
}
type AgentT[A] = Agent { type geneType = A }
def slice[A](parentA: AgentT[A], parentB: AgentT[A]): (AgentT[A], AgentT[A]) = {
val genomeSize = parentA.genome.length
require (parentB.genome.length == genomeSize)
import parentA.geneTag
val index = (math.random * genomeSize + 0.5).toInt
val (aInit, aTail) = parentA.genome.splitAt(index)
val (bInit, bTail) = parentB.genome.splitAt(index)
val genomeA = Array.concat(aInit, bTail)
val genomeB = Array.concat(bInit, aTail)
(parentA.copy(genomeA), parentB.copy(genomeB))
}
If you don't need to squeeze the last bits of performance, you could use an immutable collection such as Vector instead of Array.
case class Agent[A](genome: Vector[A]) {
def size = genome.size
}
def slice[A](parentA: Agent[A], parentB: Agent[A]): (Agent[A], Agent[A]) = {
val genomeSize = parentA.size
require (parentB.size == genomeSize)
val index = (math.random * genomeSize + 0.5).toInt
val (aInit, aTail) = parentA.genome.splitAt(index)
val (bInit, bTail) = parentB.genome.splitAt(index)
val genomeA = aInit ++ bTail
val genomeB = bInit ++ aTail
(parentA.copy(genomeA), parentB.copy(genomeB))
}