Emil Ivanov
Emil Ivanov

Reputation: 37633

Composition of PartialFunctions in Scala

I'm working with akka actors. All actors should implemented the receive method, which has a signature of PartialFunction[Any, Unit]. I want to define a stricter function to use for the matching with signature like PartialFunction[Action, Unit]. However, this doesn't compile:

class PlayerActor extends Actor with {
  override def receive: Receive = rec

  def rec: PartialFunction[Action, Unit] = {
    case Jump() =>
  }
}

I want to do this so the compiler will warn me if I forget a case.

Receive is defined as type Receive = PartialFunction[Any, Unit]


I ended up doing it manually like:

override def receive = {
  case a: Action => rec(a)
}

It can also be done by casting:

override def receive = rec.asInstanceOf[PartialFunction[Any, Unit]]

Or via an implicit conversion:

implicit def toAnyPartial[T](f: PartialFunction[T, Unit]): PartialFunction[Any, Unit] =
  f.asInstanceOf[PartialFunction[Any, Unit]]

Upvotes: 1

Views: 234

Answers (3)

senia
senia

Reputation: 38045

If all you want is to create PartialFunction[Any, Unit] using implementation of type PartialFunction[T, Unit] you could try this:

implicit def toPfAny[T](pf: PartialFunction[T, Unit]): PartialFunction[Any, Unit] = {
  object PF { def unapply(a: T): Option[Unit] = pf.lift(a) }
  { case PF(_) => () }
}

Usage:

scala> def impl: PartialFunction[String, Unit] = { case s => println(s) }
impl: PartialFunction[String,Unit]

scala> def receive: PartialFunction[Any, Unit] = impl
receive: PartialFunction[Any,Unit]

Upvotes: 1

Tesseract
Tesseract

Reputation: 8139

You could try this

def rec: Receive  = { case a: Action => a match {
  case Jump() =>
}}

Upvotes: 2

Alexander Azarov
Alexander Azarov

Reputation: 13221

PartialFunction is contravariant on its first type parameter. I shall not dig into explanation what this means (there are books, blog posts, SO questions & answers), but will give you very trivial example instead.

You are allowed to pass Any to receive. If it would be possible to assign rec to receive, it would mean you may pass Any to rec, thus bypassing rec's type. Compiler prohibits it.

Upvotes: 1

Related Questions