Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

scala, parameter type in structural refinement

Tags:

scala

akka

When I compile following code with Scala 2.11.1 and Akka 2.3.4, I get Error:

Error:(24, 35) Parameter type in structural refinement may not refer to an abstract type defined outside that refinement
  def behavior(list: List[T], ele: T):Receive={
                              ^
Error:(24, 35) Parameter type in structural refinement may not refer to a type member of that refinement
  def behavior(list: List[T], ele: T):Receive={
                              ^

The code:

package exp

import akka.actor.{ActorSystem, Props, Actor}

trait myTrait[T <: myTrait[T]]{
  def computeDistance(that: T): Double
}


class otherClass[T <: myTrait[T]](){

  def func(data: List[T]):List[String]={

    val system = ActorSystem()
    system.actorOf(Props(new Actor{
      case object START
      case class Job(e1: T, e2: T)

      def receive = {
        case START =>
          context become behavior(data.tail, data.head)
      }

      def behavior(list: List[T], ele: T):Receive={
        case _ =>
          sender ! Job(list.head, ele)
          context become behavior(list.tail, ele)
      }
    }))
    List.empty[String]
  }
}

object Test {
  class myClass(val x:Double) extends myTrait[myClass]{
    override def computeDistance(that: myClass): Double = this.x - that.x
  }

  def main(args: Array[String]){
    val fc = new otherClass[myClass]()
    fc.func(List.empty[myClass])
  }
}

The reason I define myTrait as myTrait[T <: myTrait[T]] is that I want subclass of myTrait can override computeDistance method with subclass argument. Follows this post.

otherClass provides a method func to produce some computation on a list of myClass instances. (Actually the above code is an abstraction of my need.)

Adding generic type on behavior can eliminate the above error, but it will cause new error.

def behavior[S](list: List[T], ele: S):Receive={
  case _ =>
    sender ! Job(list.head, ele)
    context become behavior(list.tail, ele)
}

Then, in Job(list.head, ele), the ele of type S mismatches type T.

How to solve this problem?

like image 631
宇宙人 Avatar asked Jul 24 '26 04:07

宇宙人


2 Answers

Adding a type annotation to widen the type to plain Actor fixes the problem:

system.actorOf(Props(new Actor{
    // ...
}: Actor))
like image 58
Owen Avatar answered Jul 25 '26 19:07

Owen


class otherClass[T <: myTrait[T]](){

  def func(data: List[T]):List[String]={

    val system = ActorSystem()
    class FooActor extends Actor {
      case object START
      case class Job(e1: T, e2: T)

      def receive = {
        case START =>
          context become behavior(data.tail, data.head)
      }

      def behavior(list: List[T], ele: T):Receive={
        case _ =>
          sender ! Job(list.head, ele)
          context become behavior(list.tail, ele)
      }
    }
    system.actorOf(Props(new FooActor))
    List.empty[String]
  }
}

Just get ride of that structural actor creation by wrapping it as a new class

like image 44
jilen Avatar answered Jul 25 '26 17:07

jilen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!