Scala type erase issue with path dependent / nested types

Assume the following:

class Wrapper1 { case class Condition(test: String) } object Wrapper1 extends Wrapper1 class Wrapper2 { case class Condition[A](test: String) } object Wrapper2 extends Wrapper2 class Test type T = // whatever def test(fn: T => Wrapper1.Condition): X def test[R](fn: T => Wrapper2.Condition[R]): X } 

The problem is that due to type erasure, these methods have the same type after erasure. It is easy to change the signature of the second with:

 def test[R](fn: T => Wrapper2.Condition[R])(implicit ev: R =:= R): X 

But this confuses the compiler and using the test method in other places is not possible. For a number of reasons, I try to keep the name of this method consistent. Is there any way to successfully do this?

+5
source share
2 answers

Finally, finally, you can work it out. What I was was a way to conditionally add to an HList . Basically, multiple overloads of the same method should coexist because they return a different type of HList .

To have only one method, arguments are needed to determine what the final signature of the method looks like.

So, suppose the following, the test method should have returned

 def test[RR](arg: Type1[RR]): Wrapper[RR :: ExistingHList] 

Or accordingly:

 def test(arg: Type2): Wrapper[ExistingList] 

The same method must be added to the HList depending on whether the argument satisfies certain conditions. The fix was as trivial as using shapeless.ops.hlist.Prepend , which by default returns an existing HList if we try to add HNil to the hlist.

Creating a Type2 argument returns HNil or implicitly converting to what will eventually be HNil - this is the approach that worked.

In particular:

  class Wrapper[PS <: HList] { def test[ RR, HL <: HList, Out <: HList ]( condition: T => Wrapper[HL] )(implicit prepend: Prepend.Aux[HL, PS, Out]): Wrapper[Out[ } 

This approach works if the condition function returns Wrapper[HNil] for situations where the function does not need to change the type of the return end. Functions that change can freely create their own HList their own.

0
source

It seems this is NOT a duplicate of Scala double definition (2 methods have erasure of the same type)

My suggestion ... Just use one method

 def test[Cond: TypeTag](fn: T => Cond): X = { if(typeOf[T] <:< typeOf[Wrapper1.Condition]) ... else if(typeOf[T] <:< typeOf[Wrapper2.Condition[_]) ... else ... } 
0
source

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


All Articles