Reputation: 3982
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.
Upvotes: 2
Views: 289
Reputation: 67828
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
Upvotes: 5