0

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?

sinwav
  • 724
  • 1
  • 7
  • 20

1 Answers1

1

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?

Community
  • 1
  • 1
sjrd
  • 21,805
  • 2
  • 61
  • 91
  • I get error: No ClassTag available for E#geneType. I tried E#geneType:ClassTag as well as suggested by another SO post with a different OP. – sinwav Jul 12 '14 at 21:43
  • Right, you also need a `ClassTag` from within `Simulation`. But you cannot conjure one up from nowhere. You'll have to require it as an additional parameter in your class: `abstract class Simulation[E <: Agent](population: Array[E])(implicit ct: ClassTag[E#geneType]) {`. Not sure this is going to work, though. I've never tried requiring a `ClassTag` of a type projection... – sjrd Jul 13 '14 at 08:34
  • that worked out, but then there were issues with the slice function due to Array invariance. I will investigate this more thoroughly. – sinwav Jul 14 '14 at 23:07