scalarecursive-type

Collection of object with self recursive type in scala


trait Node[N<:Node[N]] { self:N =>
}

trait A extends Node[A]

trait B {
  def list:List[Node[_]]

  def as:List[A] = list.collect { case x:A => x }
}

I'm having some trouble with using self recursive type in collections. In this example, the compiler gives the error

 def as = list.collect { case x:A => x }
                       ^
type arguments [_$1] do not conform to trait Node's type parameter bounds [N <: Node[N]]

because wildcard in List[Node[_]] does not conform the type bound. Is there any proper way of specifying wildcard type to recursive bound? One workaround is

  def as = {
    list match {
      case list:List[Node[n]] => list.collect { case x:A => x }
    }
  }

which is quite ugly.


Solution

  • you can solve this with an existential

    trait Node[N<:Node[N]] { self:N =>
    }
    
    trait A extends Node[A]
    
    trait B {
      def list:List[X forSome {type X <: Node[X]}]
    
      def as:List[A] = list.collect { case x:A => x }
    }
    

    just a fair warning forSome is going to be removed from scala at some point. Can you tell us more about what you're trying to do? mayber there's a more elegant way to do this