How is this a type mismatch? - scala

val eventListeners = new HashMap[Class[Event], ArrayBuffer[Event => Unit]]
def addEventListener[A <: Event](f: A => Unit)(implicit mf: ClassManifest[A]): A => Unit = {
eventListeners.getOrElseUpdate(mf.erasure.asInstanceOf[Class[Event]], ArrayBuffer[Event => Unit]()) += f
f
}
Is throwing:
error: type mismatch;
found : (A) => Unit
required: (this.Event) => Unit
eventListeners.getOrElseUpdate(mf.erasure.asInstanceOf[Class[Event]], ArrayBuffer[Event => Unit]()) += f
Why is it saying that it found (A) => Unit? The value of f is a function that is (Event) => Unit. Isn't A just a type parameter, not the signature?
Example call:
addEventListener { e:FooEvent => .... }

The class Function1 is contra-variant on its parameter. Ie, its type is Function1[-T, +R].
That means a function of Any => Unit is a subtype of Event => Unit, but for A a subtype of Event, A => Unit is a _super_type of Event => Unit.
Ergo, the problem. If you change the type parameter to A >: Event, it should work.

You are promising your ArrayBuffer that you will give it a function that can take any Event and turn it into a Unit (presumably doing something interesting along the way).
But you are giving it a function that can only take As, which may not encompass all Events. That is clearly not what you've promised, so the compiler complains.
You need to figure out what ought to happen in that case, and write code accordingly. For example, you could create a new function g that does nothing in case it receives an Event that, according to your class manifest, is not an A, and otherwise applies f. Or you could require all listeners to take events of all sorts, and be responsible themselves for throwing away the events that they don't want to bother with.
Edit: just to make things clearer with an example,
abstract class Fruit { def tasty: String }
class Banana extends Fruit { def tasty = "Yum!" }
abstract class SeededFruit extends Fruit {
def seedCount: Int
def tasty = "Mmm, mmm."
}
class Peach extends SeededFruit { def seedCount = 1 }
class Apple extends SeededFruit { def seedCount = 5 }
val tellAboutSeeds = (sf: SeededFruit) => println("There are "+sf.seedCount+"seeds")
val fruitTeller = new collection.mutable.ArrayBuffer[Fruit=>Unit]
fruitTeller += tellAboutSeeds // If this worked...
fruitTeller(0)(new Banana) // ...we'd be in trouble!

Related

How to chain generically chain functions returning Either with an operator like `andThen`?

Problem: Chaining multiple Either returning functions, the Left of which are all failures inheriting from a common sealed trait InternalError. However, the compiler complains that the chain is returning Either[_,Success] instead of Either[InternalError, Success].
Here's the code that does the chaining:
import scala.language.implicitConversions
object EitherExtension {
implicit class AndThenEither[A,B](val e: Function1[A,Either[_,B]]) {
//get ability to chain/compose functions that return aligning Eithers
def andThenE[C](f:Function1[B, Either[_,C]]): Function1[A, Either[_,C]] = {
(v1: A) => e.apply(v1).flatMap(b => f.apply(b))
}
}
}
As was pointed out in the comments this discards the type of Left. If I change it the below it will not work since the final output can be of type Either[X|Y, C] which resolves to Either[_,C] and I'm back to square one.
implicit class AndThenEither[A,B,X](val e: (A) => Either[X, B]) {
def andThenE[C,Y](f:(B) => Either[Y, C]): (A) => Either[_, C] = {
(v1: A) => e.apply(v1).flatMap(b => f.apply(b))
}
}
Here's the example showing the compositional failure of type alignment:
import EitherExtension._
object AndThenComposition {
//sample type definitions of failure responses
sealed trait InternalError
case class Failure1() extends InternalError
case class Failure2() extends InternalError
//sample type definitions
case class Id(id: Int)
case class Stuff()
//sample type definitions of successful responses
case class Output1()
case class Output2()
case class InputRequest()
val function1: (InputRequest) => Either[Failure1, Output1] = ???
val function2: (Output1) => Either[Failure2, Output2] = ???
def doSomething(s:Id, l:List[Stuff]): Either[InternalError, Output2] = {
val pipeline = function1 andThenE function2
pipeline(InputRequest()) //Why is this of type Either[_, Output2]
}
}
What am I missing? How can I get the return type to not be Either[Any, Output2] but rather the base/sealed trait? Is this possible to do generically?
You need to preserve the type of the left so we will modify the extension method to do that.
Note that, since both eithers can have different left types, what we will do is use a type bound to ask the compiler to infer the LUB between those types; thanks to Any this is always possibles (although not always helpful).
object EitherExtension {
implicit class AndThenEither[I, L1, R1](private val f: I => Either[L1, R1]) extends AnyVal {
def andThenE[L2 >: L1, R2](g: R1 => Either[L2, R2]): I => Either[L2, R2] =
i => f(i).flatMap(g)
}
}
Which can be used like this:
import EitherExtension._
object AndThenComposition {
sealed trait InternalError
final case object Failure1 extends InternalError
final case object Failure2 extends InternalError
val function1: Int => Either[Failure1.type, String] = ???
val function2: String => Either[Failure2.type, Boolean] = ???
def doSomething(input: Int): Either[InternalError, Boolean] = {
(function1 andThenE function2)(input)
}
}
See the code running here.
In case you're using this in production, and it's not just a learning thing, what you're looking for it's called Kleisli, and fortunately cats-core already implements it.
According to the cats-core docs:
Kleisli enables composition of functions that return a monadic value,
for instance an Option[Int] or a Either[String, List[Double]], without
having functions take an Option or Either as a parameter, which can be
strange and unwieldy.
Since Kleisli composes two functions with the signature A => F[B], you'd need only one abstraction to be able to use Kleisli, which is creating a new type for your operation:
type Operation[A] = Either[InternalFailure, A]
By doing this, you should be able to use Kleisli like this:
import cats.data.Kleisli
val first: Kleisli[Operation, InputRequest, Output1] = Kleisli { request: InputRequest =>
Left(Failure1())
}
val second: Kleisli[Operation, Output1, Output2] = Kleisli { output: Output1 =>
Right(Output2())
}
val composed = first.andThen(second)

Type system not allowing subtype as a type constructor

I'm trying to build the following type structure for a library I'm writing, and I'm having trouble with the type system.
CarLike
trait CarLike[T, C <: CarLike[T,C]] {
val parts: Seq[T]
def crash(other: C, speed: Int): C
//... other methods
}
SimpleCar
class SimpleCar[T](val parts: Seq[T]) extends CarLike[T, SimpleCar[T]] {
def crash(other: SimpleCar[T], speed: Int) = {
//Some logic to crash with the other car
val newParts = damage(parts) //parts have changed
new SimpleCar(newParts)
}
//...other methods
}
SportsCar
class SportsCar(val sParts: Seq[String]) extends SimpleCar[String](sParts){
override def crash(other: SimpleCar[String], speed: Int): SimpleCar[String] = {
//Some other logic for crashing a sport car
val newParts = damage(parts) //parts have changed
new SportsCar(newParts)
}
//...other methods
}
Crasher
case class Crasher[T, C <: CarLike[T,C]](
partsDamager: T => T,
carChecker: C => Seq[T]
/*... more parameters*/
){
def test(cycles:Int) = {
//Some logic to run a crash of two cars
}
}
Code
//...
val crasher = Crasher[String, SportsCar](
(s: String) => s.tail,
(c: SportsCar) => c.parts.filter(p => p.length > 0)
/*Many arguments*/
)
crasher.test(20)
//...
The idea is to allow the user of the library to be able to choose between using the default SimpleCar and implementing his own implementation of CarLike.
Also, users can choose the type for the car's parts. In this simple example the parts are String, but can easily be a custom class, which can be leveraged in the crash method of a custom class.
When compiling, I get the following compilation error:
type arguments [String,my.package.SportsCar] do not conform to method apply's type parameter bounds [T,C <: crashing.CarLike[T,C]]
val crasher = Crasher[String, SportsCar](
Clearly there's something I'm missing here. Why doesn't the compiler agree that SportsCar is a legal subtype of CarLike?
A SportsCar is not a CarLike[String, SportsCar], it is a CarLike[String, SimpleCar[String]]. Note that SportsCar extends SimpleCar[String], but that doesn't help, as CarLike is not covariant in C.
You can't really make CarLike covariant in C, as its crash method accepts a C. Instead, you can pass SimpleCar[String] to Crasher (after all, sports cars can crash with other cars, right?):
val crasher = Crasher[String, SimpleCar[String]](
s => s.tail,
c => c.parts.filter(p => p.length > 0)
)
Or, you can modify Crasher to take another type parameter:
case class Crasher[T, C <: CarLike[T, C], X <: C](partsDamager: T => T,
carChecker: X => Seq[T]) {
// ...
}
val crasher = Crasher[String, SimpleCar[String], SportsCar](
s => s.tail,
c => c.parts.filter(p => p.length > 0)
)

Scala generics: why two types with the same upper bound are not compatible?

I am confused with how bounds work in Scala generics. Consider the following:
sealed trait MessageBody
case class Body1() extends MessageBody
case class Body2() extends MessageBody
sealed trait MessageKey[T <: MessageBody]
case object Key1 extends MessageKey[Body1]
case object Key2 extends MessageKey[Body2]
type MessageHandler[B <: MessageBody] = PartialFunction[MessageKey[B], B => Unit]
abstract class Handler {
def messageHandler[B <: MessageBody]: MessageHandler[B]
}
class ProcessingHandler[ReturnType <: MessageBody](val onSuccess: MessageKey[ReturnType]) extends Handler {
override def messageHandler[B <: MessageBody]: MessageHandler[B] = {
case `onSuccess` => success
}
def success(msg: ReturnType): Unit = println(msg)
}
This gives me an error:
error: type mismatch;
found : ReturnType => Unit
required: B => Unit
case `onSuccess` => success
^
In my naive understanding, both ReturnType and B are subtypes of MessageBody and thus must be compatible. So why are they not compatible, and how should I write my code to make them compatible?
EDIT: The following piece of code works just fine, and if I mix the relation between the MessageKey and MessageBody instances anywhere, I get a nice compile time error.
class ProcessingHandler2 extends Handler {
override def messageHandler[B <: MessageBody]: MessageHandler[B] = {
case Key1 => h1
// case Key1 => h2 // gives compile-time error
case Key2 => h2
}
def h1(x: Body1): Unit = println(x)
def h2(x: Body2): Unit = println(x)
}
val handler: Handler = new ProcessingHandler2
handler.messageHandler(Key1)(Body1())
// handler.messageHandler(Key1)(Body2()) // gives compile-time error
EDIT: Obviously, there is no way to compile check this: handler.messageHandler(Key3) and this will result in a MatchError at run-time.
Let's say you have an object of type ProcessingHandler[Body1] and then call messageHandler[Body2] on it. According to the signature, it should return a Body2 => Unit, but you try to return a Body1 => Unit. If you were trying to return a MessageBody => Unit, that would be fine as MessageBody is a superclass of Body2, but Body1 is not. They're both children of the same superclass, but that doesn't make them compatible, that is you can't pass a Body2 as an argument to a function that takes a Body1 or vice versa.
Depending on what exactly your requirements are, there are multiple things you could do:
You could make Handler generic instead of messageHandler and then extend Handler[ReturnType] (or you could give Handler a member type and use it in messageHandler).
Or you could make success take a MessageBody as its argument instead of a ReturnType.

Limitations of implicit resolution or type inference

I'm trying to understand why implicit resolution (or perhaps type inference) fails for the following Scala code. In this code, compilation fails on the second to last line, but succeeds on a modified version of the line where types are explicitly provided.
object O {
trait Wrapper[-A, +B] {
def func: A => B
}
object Identity
implicit class Identity2Wrapper[A](self: Identity.type) extends Wrapper[A, A] {
override def func: A => A = identity
}
// Compilation fails on the next line with error:
// found String("hello")
// required: A
Identity.func("hello")
// This line compiles.
implicitly[Identity.type => Wrapper[String, String]].apply(Identity).func("hello")
}
Travis Brown seems to be right, this is an occurence of the following: https://issues.scala-lang.org/browse/SI-6472
As a proof, I could make it compile using the work around given by Travis himself here: https://issues.scala-lang.org/browse/SI-6776
object O {
trait Wrapper[-A, +B] {
val funcFunc: A => B
def func( arg: A ): B = funcFunc( arg )
}
private class Private
trait BaseWrappable {
// Dummy method (cannot ever be called, just a work around to help the compiler)
def func( a: Private ) = ???
}
object Identity extends BaseWrappable
implicit class Identity2Wrapper[A](self: Identity.type) extends Wrapper[A, A] {
val funcFunc: A => A = identity
}
Identity.func("hello")
}
The code you have written is the same as:
class Identity2Wrapper[A](self: Identity.type) extends Wrapper[A, A] {
override def func: A => A = identity
}
implicit def identityToIdentityWrapper[A](self: Identity.type) = new Identity2Wrapper[A](self)
Note that the type parameter A is unbound until the the result from the call to func is used. The Scala compiler is not smart enough to look that far ahead and determine the type of A. Also, you cannot create a value of type [A] A => A in Scala. I'm actually surprised that the compiler doesn't infer A to be of type Nothing like it does when you call identityToIdentityWrapper explicitly.

datastructure that holds closures, parametrically in scala

I am implementing a GUI event system in Scala. I have something like:
case class EventObject
case class KeyEventObject extends EventObject
case class MouseEventObject extends EventObject
I would like to store event listener closures in a (multi-)map, like so:
var eventListeners = new MultiMap[EventDescriptor, (EventObject => Unit)];
My question is, is there some way to rewrite this so that the function signatures of the stored closure can be EventObject or any subclass? Something like the following:
var eventListeners = new MultiMap[EventDescriptor, [A <: EventObject](A => Unit)]
so that I can have the subtype known when I define the listener functions:
eventListeners.put(KEY_EVENT, (e:KeyEventObject) => { ... })
eventListeners.put(MOUSE_EVENT, (e:MouseEventObject) => { ... })
Not that many things are impossible. You can do the following, for example, with type classes:
class HMultiMap {
import scala.collection.mutable.{ Buffer, HashMap }
type Mapping[K, V]
private[this] val underlying = new HashMap[Any, Buffer[Any]]
def apply[K, V](key: K)(implicit ev: Mapping[K, V]) =
underlying.getOrElse(key, Buffer.empty).toList.asInstanceOf[List[V]]
def add[K, V](key: K)(v: V)(implicit ev: Mapping[K, V]) = {
underlying.getOrElseUpdate(key, Buffer.empty) += v
this
}
}
And now:
sealed trait EventObject
case class KeyEventObject(c: Char) extends EventObject
case class MouseEventObject(x: Int, y: Int) extends EventObject
sealed trait EventDescriptor
case object KEY_EVENT extends EventDescriptor
case object MOUSE_EVENT extends EventDescriptor
class EventMap extends HMultiMap {
class Mapping[K, V]
object Mapping {
implicit object k extends Mapping[KEY_EVENT.type, KeyEventObject => Unit]
implicit object m extends Mapping[MOUSE_EVENT.type, MouseEventObject => Unit]
}
}
It's a little messy, but the usage is much prettier:
val eventListeners = new EventMap
eventListeners.add(KEY_EVENT)((e: KeyEventObject) => println(e.c))
eventListeners.add(MOUSE_EVENT)((e: MouseEventObject) => println("X: " + e.x))
eventListeners.add(KEY_EVENT)((e: KeyEventObject) => println(e.c + " again"))
We can confirm that we can pick out individual kinds of event handlers:
scala> eventListeners(KEY_EVENT).size
res3: Int = 2
And we can pretend to fire an event and run all the handlers for it:
scala> eventListeners(KEY_EVENT).foreach(_(KeyEventObject('a')))
a
a again
And it's all perfectly safe, since nothing gets into the underlying loosely-typed map without the proper evidence. We'd get a compile-time error if we tried to add a function from String to Unit, for example.
EDIT
Seems impossible. Also a case-to-case inheritance gets prohibited in Scala-2.10
...
Maybe by using some specific trait and declaring event object classes sealed and extend that trait?
val eventListeners = new MultiMap[EventDescriptor, ((_ >: EventTrait) => Unit)]
From List sources:
:+[B >: A, That](elem: B)(implicit bf: CanBuildFrom[List[A], B, That]): That
That - is a specific type, it could be built from your EventTrait by implicit builder, one builder for each event type. Instead of elem: B try use classOf[B]. Create get methods that will access your MultiMap using different classOf:
def getMouseEvent(ed: EventDescriptor) = multimap.entrySet.filter(
(a, b) => a == ed ).map((a, b) => (a, convertTo(ClassOf[MouseEvent], b)).
filter((a, b) => b != null)
convertTo returns null if it could not convert event to appropriate type
Ugly.
It's impossible.
Let's suppose you have such Map:
val f = eventListeners(key).head
How would you call the function f? With parameter of type EventObject? You can't. It could be KeyEventObject => Unit. With parameter of type KeyEventObject? You can't. It could be MouseEventObject => Unit.
You can use PartialFunction[EventObject, Unit] and check for isDefinedAt every time, but it's an ugly way.