Scala anonymous class type mismatch - scala

I am creating a list holding Comparable objects and wish to create one object that serves as the minimum of the list, such that it always returns -1 for its compareTo method. Other methods in the list, like print here requires an input of type A. If I compile the code I get the following error:
error: type mismatch;
found : java.lang.Object with java.lang.Comparable[String]
required: String
l.print(l.min)
Anyone have any idea about how can a create such a minimum element so that it is always smaller than any other elements in the list?
class MyList[A <: Comparable[A]] {
val min = new Comparable[A] {
def compareTo(other: A) = -1
}
def print(a: A) = {
println(a)
}
}
class Run extends Application {
val l = new MyList[String]
l.print(l.min)
}

Well, the input passed is not equal to the input provided, right? print needs an A:
def print(a: A) = {
And min does not return an A:
val min = new Comparable[A] {
As to creating such an A as you want it... how could you possibly go about it? You don't know anything about A -- you don't know what its toString returns, you don't know what methods it implements, etc.
So, basically, change your algorithm.

You are getting a compile error because you're trying to use a Comparable where the compiler is expecting a A, what you really want to do is:
val min: A = new A {
def compareTo(other: A) = -1
}
but you can't do this in Scala (or Java), because you're trying to create an object of an unknown type (A). You could do this using reflection, but you would still have the problem of creating an object which was less than any other object in the list.
Also, be aware that your implementation of compareTo will have problems with almost any sorting algorithm you choose, because you can't guarantee compareTo is always called from min. For example, you could get:
min.compareTo(list(0)) // returns -1
list(0).compareTo(min) // could be anything really
If you want a list that returns a specific object as the 'minimum' then you could just prepend a specific value to the sorted list:
class MyList2[A <: Comparable[A]] {
val min: A; // somehow create an instance of the class A
val list: List[A]
def sort(fn: (A, A) => Boolean) = {
min :: list.sort(fn)
}
}
but as Daniel says, this is probably the wrong way to go about it.

Related

Scala cast to generic type

I'm confused about the generic type. I expect that 2.asInstanceOf[A] is cast to the type A, meanwhile, it's cast to Int.
Besides that, the input is java.lang.Long whereas the output is a list of Int (according to the definition the input and the output should be the same type). Why is that?
def whatever[A](x: A): List[A] = {
val two = 2.asInstanceOf[A]
val l = List(1.asInstanceOf[A],2.asInstanceOf[A])
println(f"Input type inside the function for 15L: ${x.getClass}")
println(f"The class of two: ${two.getClass}, the value of two: $two")
println(f"The class of the first element of l: ${l.head.getClass}, first element value: ${l.head}")
l
}
println(f"Returned from whatever function: ${whatever(15L)}")
the outupt:
Input type inside the function for 15L: class java.lang.Long
The class of two: class java.lang.Integer, the value of two: 2
The class of the first element of l: class java.lang.Integer, first element value: 1
Returned from whatever function: List(1, 2)
a.asInstanceOf[B] means:
Dear compiler;
Please forget what you think the type of a is. I know better. I know that if a isn't actually type B then my program could blow up, but I'm really very smart and that's not going to happen.
Sincerely yours, Super Programmer
In other words val b:B = a.asInstanceOf[B] won't create a new variable of type B, it will create a new variable that will be treated as if it were type B. If the actual underlying type of a is compatible with type B then everything is fine. If a's real type is incompatible with B then things blow up.
Type erasure. For the purposes of type checking 2 is cast to A; but at a later compilation stage A is erased to Object, so your code becomes equivalent to
def whatever(x: Object): List[Object] = {
val two = 2.asInstanceOf[Object]
val l = List(1.asInstanceOf[Object],2.asInstanceOf[Object])
println(f"Input type inside the function for 15L: ${x.getClass}")
println(f"The class of two: ${two.getClass}, the value of two: $two")
println(f"The class of the first element of l: ${l.head.getClass}, first element value: ${l.head}")
l
}
2.asInstanceOf[Object] is a boxing operation returning a java.lang.Integer.
If you try to actually use the return value as a List[Long] you'll eventually get a ClassCastException, e.g.
val list = whatever(15L)
val x = list(0)
x will be inferred to be Long and a cast inserted to unbox the expected java.lang.Long.
The answer from #jwvh is on point. Here I'll only add a solution in case you want to fix the problem of safely converting an Int to an A in whatever, without knowing what A is. This is of course only possible if you provide a way to build a particular A from an Int. We can do this in using a type-class:
trait BuildableFromInt[+A] {
def fromInt(i: Int): A
}
Now you only have to implicitly provide BuildableFromInt for any type A you wish to use in whatever:
object BuildableFromInt {
implicit val longFromInt: BuildableFromInt[Long] = Long.box(_)
}
and now define whatever to only accept compliant types A:
def whatever[A : BuildableFromInt](x: A): List[A] = {
val two = implicitly[BuildableFromInt[A]].fromInt(2)
// Use two like any other "A"
// ...
}
Now whatever can be used with any type for which a BuildableFromInt is available.

HList/KList from class values

I want to be able to create a class/trait that behaves somewhat like an enumeration (HEnum in the first snippet below). I can't use a plain enumeration because each enum value could have a different type (though the container class will be the same): Key[A]. I'd like to be able to construct the enum roughly like this:
class Key[A](val name: String)
object A extends HEnum {
val a = new Key[String]("a")
val b = new Key[Int]("b")
val c = new Key[Float]("c")
}
And then I'd like to be able to perform more or less basic HList operations like:
A.find[String] // returns the first element with type Key[String]
A.find("b") // returns the first element with name "b", type should (hopefully) be Key[Int]
So far I've been playing with an HList as the underlying data structure, but constructing one with the proper type has proven difficult. My most successful attempt looks like this:
class Key[A](val name: String)
object Key {
def apply[A, L <: HList](name: String, l: L): (Key[A], Key[A] :: L) = {
val key = new Key[A](name)
(key, key :: l)
}
}
object A {
val (a, akeys) = Key[String, HNil]("a", HNil)
val (b, bkeys) = Key[Int, Key[String] :: HList]("b", akeys)
val (c, ckeys) = Key[Float, Key[Int] :: HList]("c", bkeys)
val values = ckeys // use this for lookups, etc
def find[A]: Key[A] = values.select[A]
def find[A](name: String): Key[A] = ...
}
The problem here is that the interface is clunky. Adding a new value anywhere besides the end of the list of values is error prone and no matter what, you have to manually update values any time a new value is introduced. My solution without HList involved a List[Key[_]] and error prone/unsafe casting to the proper type when needed.
EDIT
I should also mention that the enum example found here is not particularly helpful to me (although, if that can be adapted, then great). The added compiler checks for exhaustive pattern matches are nice (and I would ultimately want that) but this enum still only allows a homogeneous collection of enum values.

Scala: Preference among overloaded methods with implicits, currying and defaults

The following simple piece of code fails to compile:
object O {
def apply(s:String, o:Int=5)(implicit i:String) = {
println("am first");
s
}
def apply(s:String)(o:Boolean*) = {
println("am second");
o
}
}
object Main extends App {
implicit val myS = "foo"
O("test")
}
The error being
error: missing arguments for method apply in object O;
follow this method with `_' if you want to treat it as a partially applied function
O("test")
^
one error found
This appears to be because the compiler prefers the second apply. But why is this? Especially considering that the conditions for applying the first apply are satisfied? If I delete the second apply the piece of code compiles fine.
Are there any way to "guide" the compiler towards compiling this correctly? Or am I forced to create two different method names?
You're right that it is possible for the Scala compiler to be smarter. The problem is that noone has wanted to come up with the new specification for this. It'll be very complicated.
There are ways to get around this limitation.
1. replace overloading with pattern matching within apply to choose one of the two functions
def apply(s: String, i: Option[Int] = None) = {
i match {
case Some(n) => // call the 1st
case None => // call the 2nd
}
}
Then:
apply("test", Some(5)) => ... // if we want the first
apply("test") => ... // if we want the second
2. use overloading but with different parameter names for the two functions:
def apply(apple: String, o: Int = 5)(implicit i: String)
def apply(banana: String)(o: Boolean*)
Then:
apply(apple = "test") // if we want the first
apply(banana = "test") // if we want the second
Let's regard this situation without implicits
object O {
def apply(s: String, o: Int = 5) = {
println("am first")
}
def apply(s: String) = {
println("am second")
}
}
In this situation O("test") will be compiled with second apply, so you can't use default parameters in this situation. Implicits changes nothing here. If you'll explicitly provide Int parameter, you cod will compile with first apply.

Scala trait and its methods’ parametrization

In my application I want to use such a trait:
trait HasBuffer[+A] {
var items = Buffer[A]()
def add[A](item: A) { items += item }
def remove[A](item: A) { items -= item }
def set(is: Buffer[A]) { items = is }
def clear { items clear }
}
Classes that inherit this trait should be able to buffer any instances of classes who are children of the class A. However on both the add and remove methods the compiler complains about the item being added or removed from the items that "type mismatch; found : item.type (with underlying type A) required: A". How should I understand this? What is my mistake here and what to do?
You are parameterizing the methods with another type parameter A that differs from the one of your class definition. Here's the version you wrote with renamed parameters:
trait HasBuffer[+A] {
var items = Buffer[A]()
def add[B](item: B) = items += item
def remove[B](item: B) { items -= item }
def set(is: Buffer[A]) { items = is }
def clear { items clear }
}
Now it should be clear, why the compiler rejects this.
Instead you can simply write the methods like this:
def add(item: A) = items += item
def remove(item: A) { items -= item }
However, then you will still receive compiler errors stating that covariant type A occurs in contra- and invariant positions.
The point of being covariant is that if you expect a HasBuffer[AnyVal] one may pass in a HasBuffer[Int]. However, if you expect AnyVal and use that type for the add method as well, you would be able to add a completely different type to your HasBuffer[Int]. Hence, the compiler rejects this.
Instead, you will have to provide a lower bound on the type parameter like this:
trait HasBuffer[+A, V <: A] {
var items = Buffer[V]()
def add(item: V) = items += item
def remove(item: V) { items -= item }
def set(is: Buffer[V]) { items = is }
def clear { items clear }
}
With this you may now have methods like the following:
def doSomething[X <: AnyVal](b : HasBuffer[AnyVal, X], e : X) = b.add(e)
This method will work on all sorts of HasBuffer type parameter combinations that satisfy the required lower bound.
Mentally compare this with the idea of not providing a lower bound. Then the method would have become something like this:
// doesn't make much sense!
def doSomething(b : HasBuffer[AnyVal], e : AnyVal) = b.add(e)
If you call this with an object of type HasBuffer[Int] and a Double it'll be all happy. You probably won't be happy lateron though, when you find your buffer that should contain only Ints now contains a Double.
The problem is that you have defined the add and remove methods with respect to another type parameter A that, although it has the same name, is really a new type parameter.
This should get you going:
def add(item: A)
def remove(item: A)
EDIT: Frank is right, I forgot to deal with the fact that Buffer is covariant in A where in the original declaration, A is clearly in a contravariant position. Hence the above is only a partial solution to the OP's problem.

Scala compiler not recognizing a view bound

I've tried this line of code
def **[A <% Numeric[A]](l:List[A],m:List[A])=l.zip(m).map({t=>t._1*t._2})
However on compilation, I get this error
error: value * is not a member of type parameter A
def **[A <% Numeric[A]](l:List[A],m:List[A])=l.zip(m).map({t=>t._1*t._2})
When I look at the source for the Numeric trait, I see a * op defined.
What am I doing wrong?
The instance of Numeric is not a number itself, but it is an object that offers operations to do the arithmetic. For example, an object num of type Numeric[Int] can add two integers like this: num.plus(3, 5) The result of this operation is the integer 7.
For integers, this is very trivial. However, for all basic numerical types, there is one implicit instance of Numeric available. And if you define your own numeric types, you can provide one.
Therefore, you should leave the bounds for A open and add an implicit parameter of type Numeric[A], with which you do the calculations. Like this:
def **[A](l:List[A],m:List[A])(implicit num:Numeric[A])=l.zip(m).map({t=>num.times(t._1, t._2)})
Of course, num.times(a,b) looks less elegant than a*b. In most of the cases, one can live with that. However, you can wrap the value a in an object of type Ops that supports operators, like this:
// given are: num:Numeric[A], a:A and b:A
val a_ops = num.mkNumericOps(a)
val product = a_ops * b
Since the method mkNumericOps is declared implicit, you can also import it and use it implicitly:
// given are: num:Numeric[A], a:A and b:A
import num._
val product = a * b
You can also solve this with a context bound. Using the context method from this answer, you can write:
def **[A : Numeric](l:List[A],m:List[A]) =
l zip m map { t => context[A]().times(t._1, t._2) }
or
def **[A : Numeric](l:List[A],m:List[A]) = {
val num = context[A]()
import num._
l zip m map { t => t._1 * t._2 }
}