Features of various types of path dependent types in scala

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) 
+6
source share
2 answers

T#InnerType means "A Internal type belonging to some T", and x.InnerType means "A Internal type belonging to the given x (type OuterTrait)".

The key here in understanding these values ​​is in some T vs at a given x. You can interpret some as some Ts, but we don’t have that T instance, which means that in two Ts Ts are not necessarily the same, therefore T # InnerType cannot be proved that it is equal to another T # InnerType.

Analyze Signatures:

 /* 1 */ def someAlgoObjObj[T <: OuterTrait](x: T)(y: x.InnerType): x.InnerType = ??? /* 2 */ def someAlgoObjType[T <: OuterTrait](x: T)(y: x.InnerType): T#InnerType = ??? /* 3 */ def someAlgoTypeType[T <: OuterTrait](x: T)(y: T#InnerType): T#InnerType = ??? 
  • Given that x and InnerType belonging to this x return their InnerType.
  • Given that x and InnerType belonging to this x return an InnerType belonging to some T, which means that some T is not necessarily the same instance as x.
  • Given that x and InnerType belonging to some T return InnerType belonging to some T

Now for the fourth:

 def someAlgoTypeObj[T <: OuterTrait](x: T)(y: T#InnerType): x.InnerType = y 

The signature reads: given x and InnerType belonging to some T, returns InnerType belonging to this x. But in the implementation, we try to return y that belongs to T, which does not necessarily coincide with x, so the compiler complains.

0
source

A small note about the update .

 someAlgoTypeType[OuterTrait](x)(y) 

Fails because your method signature reports that it expects its y parameter to be of type T#InnerType and your y.type to Int. To make it work, you must change its type as follows:

 class OuterIntClass extends OuterTrait{ type InnerType = Int } val x: OuterIntClass = new OuterIntClass() val y: x.InnerType = 5 

Now type y satisfies projections of type T#InnerType and someAlgoTypeType[OuterTrait](x)(y) compiles

0
source

Source: https://habr.com/ru/post/947941/


All Articles