How do I convert the following F-Bound Polymorphism to code using Abstract Types?
trait Organism[Self <: Organism[Self]] { self: Self =>
def reproduc
There are various ways to do this. Here is one way that I like, that is similar to "parameterized modules" OCaml or Agda.
When you define your Organism
type, you split it into an abstract type Organism
and a trait OrganismOps
. Then you wrap both of these in a trait:
trait OrganismSystem {
type Organism <: OrganismOps
trait OrganismOps {
def reproduceWith(org: Organism): Boolean
}
}
Because they are wrapped in the same trait, OrganismOps
can see the Organism
type.
Now if you want to create a concrete instance of these things, you would do this:
object MyOrganismSystem extends OrganismSystem {
case class Organism(species: String) extends OrganismOps {
def reproduceWith(org: Organism) = species == org.species
}
}
And if you want to define methods that operate generically on organism systems, you would have them take in an OrganismSystem
as a parameter, or, equivalently, wrap them in a class that takes an OrganismSystem
as a parameter:
class UsesGenericOrganismSystem(system: OrganismSystem) {
import system._
def allCompatible(organisms: Traversable[Organism]): Boolean =
organisms.toSeq.combinations(2) forall {
case Seq(o1, o2) => o1.reproduceWith(o2)
}
}