- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Scala Actors avoiding type-safety?
Mon, 2011-03-14, 01:26
I noticed a lot of interesting things in scala actors trunk, like CanReply. I love the idea of where this is going so I decided to try it out. However, it looks like there's an issue with trying to do a typed override that hoses up the type system on the library, actively preventing me from attempting type safety.
Here's an example:
scala> class MyActor extends Actor with InputChannel[MyMessage] { | def act() = Actor.loop { | react { | case x => println(x) | } | } | }<console>:12: error: missing parameter type for expanded functionThe argument types of an anonymous function must be fully known. (SLS 8.5) Expected type was: ? react { ^
vs.
scala> class MyActor extends Actor { | def act() = Actor.loop { | react { case x => println(x) } | } | }defined class MyActor
It seems to me that the type (Actor extends InputChannel[Any]) with InputChannel[MyMessage] should either choose to be an InputChannel[Any] or an InputChannel[MyMessage] based on variance.
I was hoping that I could make the internal API (react, receive, reactWIthin) be type safe and gain the sealed trait safety mechanisms in pattern matches. However, it appears this does nothing useful right now.
As another aside, the InputChannel[+Msg] trait appears to only use the Msg class in a few of its methods, not all of them. This gives me the false security of a type-safe interface because I can't actually use receiveWithin and get type safety with InputChannel (it accepts Any). Is that a overlooked portion of the API or is there some other reason that it can't be made to use the Msg type parameter?
- Josh
Here's an example:
scala> class MyActor extends Actor with InputChannel[MyMessage] { | def act() = Actor.loop { | react { | case x => println(x) | } | } | }<console>:12: error: missing parameter type for expanded functionThe argument types of an anonymous function must be fully known. (SLS 8.5) Expected type was: ? react { ^
vs.
scala> class MyActor extends Actor { | def act() = Actor.loop { | react { case x => println(x) } | } | }defined class MyActor
It seems to me that the type (Actor extends InputChannel[Any]) with InputChannel[MyMessage] should either choose to be an InputChannel[Any] or an InputChannel[MyMessage] based on variance.
I was hoping that I could make the internal API (react, receive, reactWIthin) be type safe and gain the sealed trait safety mechanisms in pattern matches. However, it appears this does nothing useful right now.
As another aside, the InputChannel[+Msg] trait appears to only use the Msg class in a few of its methods, not all of them. This gives me the false security of a type-safe interface because I can't actually use receiveWithin and get type safety with InputChannel (it accepts Any). Is that a overlooked portion of the API or is there some other reason that it can't be made to use the Msg type parameter?
- Josh
Tue, 2011-03-15, 00:07
#2
Re: Scala Actors avoiding type-safety?
So... If i wanted thwarting compiler to warn me of unhandled messages, id want
this.asInstanceOf[InputChannel[MyMessageType].react {
case ....
}
?
On Mar 14, 2011 6:32 PM, "Philipp Haller" <philipp.haller@epfl.ch> wrote:
Hi Josh,
On Mar 14, 2011, at 1:26 AM, Josh Suereth wrote:
Basically, you are trying to override methods of `Actor` with methods of `InputChannel[MyMessage]`. This fails, since `Actor` extends `InputChannel[Any]`:
>
> It seems to me that the type (Actor extends Inp...
test.scala:4: error: overriding method ? in trait InputChannel of type => String; method ? in trait Actor of type => Any has incompatible type class MyActor extends Actor with InputChannel[String] ^ one error found
Since `Msg` in `InputChannel[+Msg]` is covariant, `InputChannel[MyMessage] <: InputChannel[Any]`. Therefore, one might want to conclude that `(Actor extends InputChannel[Any]) with InputChannel[MyMessage] <: InputChannel[MyMessage]`.
> As another aside, the InputChannel[+Msg] trait appears to only use the Msg class in a few of its m...
The only methods in the `InputChannel[+Msg]` trait that don't use the `Msg` type are `receiveWithin` and `reactWithin`. And the reason why is that there it must be possible to pass partial functions which are defined at `TIMEOUT` (an object in `scala.actors`). Since it is not possible to constrain `Msg` to be "any type union the singleton type that includes `TIMEOUT`" these methods take a `PartialFunction[Any, R]` or `PartialFunction[Any, Unit]`, respectively, as arguments.
Cheers, Philipp
On Mar 14, 2011, at 1:26 AM, Josh Suereth wrote:
Basically, you are trying to override methods of `Actor` with methods of `InputChannel[MyMessage]`. This fails, since `Actor` extends `InputChannel[Any]`:
test.scala:4: error: overriding method ? in trait InputChannel of type => String; method ? in trait Actor of type => Any has incompatible type class MyActor extends Actor with InputChannel[String] ^ one error found
Since `Msg` in `InputChannel[+Msg]` is covariant, `InputChannel[MyMessage] <: InputChannel[Any]`. Therefore, one might want to conclude that `(Actor extends InputChannel[Any]) with InputChannel[MyMessage] <: InputChannel[MyMessage]`.
The only methods in the `InputChannel[+Msg]` trait that don't use the `Msg` type are `receiveWithin` and `reactWithin`. And the reason why is that there it must be possible to pass partial functions which are defined at `TIMEOUT` (an object in `scala.actors`). Since it is not possible to constrain `Msg` to be "any type union the singleton type that includes `TIMEOUT`" these methods take a `PartialFunction[Any, R]` or `PartialFunction[Any, Unit]`, respectively, as arguments.
Cheers, Philipp