I've defined the following class, PositionSpace, which has nested classes Position and SubPositionSpace. SubPositionSpace is itself both a Position and a PositionSpace (so it is a position that also has its own positions defined). I've defined a wrapper class, SubPosition, so that any object of type x.SubPositionSpace#Position (for any object x that is a PositionSpace) can be used as an object of type x.Position. However, I would like to make this conversion implicit, and that's where I'm stuck. Logically, it should be possible. But, I can't figure out where or how to define the conversion so that the compiler finds it, and it's making my head hurt.
Below is my code. Note that I've added test cases to the bottom.
class PositionSpace { positionSpace =>
//snip
trait Position extends Ordered[Position] {
//snip
}
class SubPositionSpace() extends PositionSpace with Position { subPositionSpace =>
//snip
//wrapper class to treat a x.SubPositionSpace#Position as a x.Position for some x : PositionSpace
//want to make this conversion implicit!!!
class SubPosition(private val subPositionIndex : subPositionSpace.Position) extends positionSpace.Position {
//snip
}
}
def append() = new Position{
//snip
}
def appendSubSpace() = new SubPositionSpace()
}
object TestCases {
val positionSpace = new PositionSpace()
val subSpace = positionSpace.appendSubSpace()
val subSpacePosition = subSpace.append()
//Does not compile, needs an implicit conversion:
val subSpacePositionAsPosition : positionSpace.Position = subSpacePosition
val subSubSpace = subSpace.appendSubSpace()
//Does not compile, needs an implicit conversion:
val subSubSpacePositionAsPosition : positionSpace.Position = subSubSpace
}
Roadblocks I've Encountered So Far
Path-Dependent Types
Part of the problem seems to be that this conversion involves path-dependent types where the input type and the output type uses the same path. However, there is no syntax to write a method with a signature of type x.Position => y.Position where y : PositionSpace and x : y.SubPositionSpace.
The problem is easy to solve by adding an additional argument to pass in the path (like below), but you can't add additional arguments to implicit conversion methods (if you want them to be used as such).
//Too many arguments, won't be used by compiler for implicit conversions
implicit def promotePosition(y : PositionSpace, x : y.PositionSpace, x.Position) : y.Position = ...