Thanks to this post I'm getting my head around dependent method types. I have a structure similar to the following
trait Environment{
type Population <: PopulationBase
protected trait PopulationBase
def evolveUs(population: Population): Population
}
object FactoredOut{
def evolvePopulation(env: Environment)(prevPopulation: env.Population): env.Population = {
env.evolveUs(prevPopulation)
}
}
I now want to start using actors to spread the work in the FactoredOut
part across a cluster. To do this I need a way to pass immutable messages which carry the Environment
.
Obviously the following doesn't work, but demonstrates what I'm trying to do
object Messages{
case class EvolvePopulation(env: Environment)(prevPopulation: env.Population)
}
What is the correct way to pass the population and it's enclosing environment around?
(Would have added the dependent-method-types tag, but I don't have enough points to add a 'new' tag)
Your intuition that you need to pack up both the value of the dependent type (env.Population
) and the value that the type depends on (env
) as a single object is exactly right.
Given the definitions you've already posted, probably the simplest approach would be something like this,
// Type representing the packaging up of an environment and a population
// from that environment
abstract class EvolvePopulation {
type E <: Environment
val env : E
val prevPopulation : env.Population
}
object EvolvePopulation {
def apply(env0 : Environment)(prevPopulation0 : env0.Population) =
new EvolvePopulation {
type E = env0.type
val env : E = env0 // type annotation required to prevent widening from
// the singleton type
val prevPopulation = prevPopulation0
}
}
Now if we define a concrete environment type,
class ConcreteEnvironment extends Environment {
class Population extends PopulationBase
def evolveUs(population: Population): Population = population
}
we can use it directly as before,
val e1 = new ConcreteEnvironment
val p1 = new e1.Population
val p2 = e1.evolveUs(p1)
val p3 = e1.evolveUs(p2)
and we can also package up an environment and population for distribution,
def distrib(ep : EvolvePopulation) {
import ep._
val p4 = env.evolveUs(prevPopulation)
val p5 = env.evolveUs(p4)
val p6 = env.evolveUs(p5)
}
val ep1 = EvolvePopulation(e1)(p3)
distrib(ep1)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With