1

This is a scala problem caused by path-dependent type: Considering that I have a family type:

trait Outer {
  
  case class Inner(v: Int) {

    val outer = Outer.this
  }
}

If I want to call Outer#Inner.copy() when the instance of Outer is unknown:

def cp(src: Outer#Inner) = {
  src.copy()
}

I will run into a compilation error. as the type signature of src.copy() is attached to its outer instance.

One way to bypass this is to extract the outer instance manually:

def cp(src: Outer#Inner) = {
  val o = src.outer
  val _src = src.asInstanceOf[o.Inner]

  _src.copy()
}

This can compiler successfully, but the asInstanceOf[] is clearly a hacking artefact and should be removed.

In idiomatic scala, what's the best way to achieve the same goal, while let the scala compiler automatically infer the existence of outer, and generate the correct type signature without blind type casting?

tribbloid
  • 4,026
  • 14
  • 64
  • 103

1 Answers1

1

Instead of Outer#Inner, you need to constrain the Outer type using a type parameter. Try

def cp[O <: Outer](src: O#Inner): O#Inner = src.copy()

This will let you maintain O#Inner, which refers to one specific type, as opposed to Outer#Inner.

See it in Scastie.

user
  • 7,435
  • 3
  • 14
  • 44
  • strange, it doesn't work for me. Just got type mismatch; found : (some other)_1.type(in method cp)#universe.Type where type (some other)_1.type(in method cp) <: R with Singleton required: _1.type(in method cp)#universe.Type where type _1.type(in method cp) <: R with Singleton – tribbloid Apr 16 '21 at 21:50
  • Sorry different scenario, published to Part2: https://stackoverflow.com/questions/67132770/in-scala-2-13-why-implicit-sometimes-can-be-summoned-directly-but-not-indirect. Thanks a lot for the answer! – tribbloid Apr 16 '21 at 22:13
  • Also, your Scastie has a message: reflective access of structural type member value inner should be enabled by making the implicit value scala.language.reflectiveCalls visible. ---- Obviously it means the code is not efficient. So probably not the ideal answer – tribbloid Apr 16 '21 at 22:25
  • @tribbloid I don't know why you're getting a type mismatch, let me work on that. As for the warning, it's just because I used a structural type instead of a class extending Outer. That has nothing to do with the method `cp`, just the other object I'm using, so you don't need to worry about its efficiency. – user Apr 16 '21 at 22:31
  • 1
    The mismatch was for a different scenario, sorry for the confusion – tribbloid Apr 17 '21 at 22:50