Question

Consider this snippet defining a trait for the state of a simulation, which a user is expected to implement in some derived type. On the trait, a collection of utility methods should be able to provide results that have the type of the implementation, similar to the way the Scala library collections do this. To achieve that, I think I need to parameterize the trait with the implementation type, like this:

trait State[+This <: State[This]] {
   def update : This  // result has type of State's implementor
}

Now I would like to define a multi-step update method, like this:

def update(steps: Int) : This 

When I try the naive approach:

def update(steps: Int) : This = 
    (this /: (0 until steps))( (s,n) => s.update )

the compiler complains about a type mismatch:

 error: type mismatch;
 found: State[This]
 required: This

which makes sense, since this, seen within State, has type State[This]. To get the code to compile, it seems I have to do an explicit cast:

def update(steps: Int) : This = 
    (this.asInstanceOf[This] /: (0 until steps))( (s,n) => s.update )

Is there a way to avoid this explicit cast, or more generally to achieve the intended result in a better way? Thanks.

Was it helpful?

Solution

You need to add a self-type annotation to ensure that State is a This:

trait State[+This <: State[This]] { this: This =>
  def update: This  // result has type of State's implementor
}

A possible way to redefine the update(Int) method without a fold would be:

def update(steps: Int): This = Iterator.iterate(this)(_.update).drop(steps).next
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top