I want to convert F bounded polymorphism to abstract type members.
trait FBoundedMovable[Self <: FBoundedMovable[Self]] { def moveTo(pos: Vect2): Self }
to
trait Movable { self => type Self <: (Movable { type Self = self.Self }) def moveTo(pos: Vect2): Self }
So far so good.
Defines an instance:
case class Ship(pos: Vect2) extends Movable { type Self = Ship def moveTo(pos: Vect2) = copy(pos = pos) }
And try using it:
// [error] found : a.Self // [error] required: A def move[A <: Movable](a: A, to: Vect2): A = a.moveTo(to)
The limited version of F works fine.
def moveF[A <: FBoundedMovable[A]](a: A, to: Vect2): A = a.moveTo(to)
I know that you can add type constraints to a method definition site:
def move2[A <: Movable { type Self = A }](a: A, to: Vect2): A = a.moveTo(to)
But is it possible to indicate a connection in the declaration with a moving attribute? If not, why?
Change 1
I realized what the problem is.
Suppose we want to declare that something is a unit in our world.
trait WorldUnit extends Movable with Damageable
All units are movable and may be damaged.
Our material for calculating the battle only cares that the material is Movable with Damagable . He does not care if it is a unit or a building.
However, we can have this code:
def doCombat(obj: Movable with Damagable) = obj.moveTo(...).takeDamage(...) def doStuffWithUnit(obj: WorldUnit): WorldUnit = doCombat(obj) // and the type is lost here.
Am I Doomed To F Limited Types?
Edit 2:
The question does not answer The attempt to model the F-bounded polymorphism as a type member in Scala - I have tried this before, and this does not affect the return type in the least, it is still itself.
Edit 3:
I found http://blog.jessitron.com/2014/02/when-oo-and-fp-meet-mytype-problem.html but the problem is still not resolved.
Basically, whenever you have a collection and you want to select it:
(collection: Seq[Movable]).collectFirst { m: Movable if m.someCondition => m } - you have no way to specify a type constraint, so the compiler cannot prove that A # Self =: = A?