Suppose there is a sign:
trait OuterTrait { type InnerType }
Now we can write the non-generic function someAlgo :
def pairToString[S, U](x: S, y: U): String = "{" + y.toString + " in " + x.toString + "}" def pairPrintln[S, U](x: S, y: U) { println(pairToString(x, y)) } def someAlgo(x: OuterTrait)(y: x.InnerType): x.InnerType = { pairPrintln(x, y) y }
and a number of common functions:
def someAlgoObjObj[T <: OuterTrait](x: T)(y: x.InnerType): x.InnerType = { pairPrintln(x, y) y } def someAlgoObjType[T <: OuterTrait](x: T)(y: x.InnerType): T#InnerType = { pairPrintln(x, y) y } def someAlgoTypeType[T <: OuterTrait](x: T)(y: T#InnerType): T#InnerType = { pairPrintln(x, y) y }
And another common function does not compile:
def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = { pairPrintln(x, y) y }
It seems that: 1) someAlgo and someAlgoObjObj are the most correct functions; 2), and it makes no sense to use a common function in this example.
And I would like to clarify some of the differences between generic functions above. Please correct me if I make mistakes.
So, as I understand it, the type T corresponds to the static type x (let's call it x ) or the explicit type of the general call (for example, algo[Int] ). Therefore, T#InnerType matches the type in the declaration of type x . But x.InnerType also matches the InnerType static type x . Where is the difference?
Next ... someAlgoObjType compiles, so it seems that x.InnerType should be a subtype of T#InnerType . Then everything is fine that someAlgoTypeObj does not compile, since we cannot do uncastly implicitly. Although we can rewrite the latter:
def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = { pairPrintln(x, y) y.asInstanceOf[x.InnerType] }
UPD1: I found one difference between someAlgoObjObj and someAlgoTypeType if used with an explicit parameter type. If we write some class extending OuterTrait :
class OuterIntClass extends OuterTrait{ type InnerType = Int } val x: OuterIntClass = new OuterIntClass() val y: Int = 5
Then:
someAlgoObjObj[OuterTrait](x)(y) // OK
and the following call does not work:
someAlgoTypeType[OuterTrait](x)(y)