I'm having trouble converting a java SortedMap into a scala TreeMap. The SortedMap comes from deserialization and needs to be converted into a scala structure before being used.
Some background, for the curious, is that the serialized structure is written through XStream and on desializing I register a converter that says anything that can be assigned to SortedMap[Comparable[_],_] should be given to me. So my convert method gets called and is given an Object that I can safely cast because I know it's of type SortedMap[Comparable[_],_]. That's where it gets interesting. Here's some sample code that might help explain it.
// a conversion from comparable to ordering
scala> implicit def comparable2ordering[A <: Comparable[A]](x: A): Ordering[A] = new Ordering[A] {
| def compare(x: A, y: A) = x.compareTo(y)
| }
comparable2ordering: [A <: java.lang.Comparable[A]](x: A)Ordering[A]
// jm is how I see the map in the converter. Just as an object. I know the key
// is of type Comparable[_]
scala> val jm : Object = new java.util.TreeMap[Comparable[_], String]()
jm: java.lang.Object = {}
// It's safe to cast as the converter only gets called for SortedMap[Comparable[_],_]
scala> val b = jm.asInstanceOf[java.util.SortedMap[Comparable[_],_]]
b: java.util.SortedMap[java.lang.Comparable[_], _] = {}
// Now I want to convert this to a tree map
scala> collection.immutable.TreeMap() ++ (for(k <- b.keySet) yield { (k, b.get(k)) })
<console>:15: error: diverging implicit expansion for type Ordering[A]
starting with method Tuple9 in object Ordering
collection.immutable.TreeMap() ++ (for(k <- b.keySet) yield { (k, b.get(k)) })
Firstly, to clarify your error:
// The type inferencer can't guess what you mean, you need to provide type arguments.
// new collection.immutable.TreeMap
// <console>:8: error: diverging implicit expansion for type Ordering[A]
//starting with method Tuple9 in object Ordering
// new collection.immutable.TreeMap
// ^
You can write an implicit to treat Comparable[T] as Ordering[T] as follows.
// This implicit only needs the type parameter.
implicit def comparable2ordering[A <: Comparable[A]]: Ordering[A] = new Ordering[A] {
def compare(x: A, y: A) = x.compareTo(y)
}
trait T extends Comparable[T]
implicitly[Ordering[T]]
However, if you really don't know the type of the key, I don't think you can create the Ordering in terms of Comparable#compareTo, at least without reflection:
val comparableOrdering = new Ordering[AnyRef] {
def compare(a: AnyRef, b: AnyRef) = {
val m = classOf[Comparable[_]].getMethod("compareTo", classOf[Object])
m.invoke(a, b).asInstanceOf[Int]
}
}
new collection.immutable.TreeMap[AnyRef, AnyRef]()(comparableOrdering)
You can probably also just give an explicit type to the TreeMap. That's how I just solved a similar problem:
collection.immutable.TreeMap[whatever,whatever]() ++ ...
(Sorry, I don't have the time to check how exactly this applies to the sources posted in the question.)
Related
I need help understanding this type signature:
def func[A : Ordering : ClassTag](a: A) = ???
I've come up with dummy examples using the type signature above... and also the type signature I'm more familiar with, that I believe is the close to the same thing based on my dummy example, but I can also come up with a toy example where they are clearly not the same.
These two seem similar:
import scala.reflect.ClassTag
// type signature in question
def func1[A : Ordering : ClassTag](elems: A*) =
Array[A](elems: _*).sorted
// my typical type signature
def func2[A <% Ordered[A]](elems: A*)(implicit c: ClassTag[A]) =
Array[A](elems: _*).sorted
Example use:
class BB(val i: Int) extends Ordered[BB] {
def compare(that: BB): Int = that.i - i
override def toString = s"BB(${i})"
}
func1(new BB(33), new BB(100), new BB(-1))
func2(new BB(33), new BB(100), new BB(-1))
Output for each is:
Array[BB] = Array(BB(100), BB(33), BB(-1))
The one edge case I can come up with where they differ... indicating one is not simply syntactic sugar for the other... is the following, where the function has an implicit order for a class that differs from the class's natural sort order.
This example (below) works fine, and implicit val ordering overrides class BB's natural sort order as I (kind of) expected.
def func3[A <% Ordered[A] : ClassTag](elems: A*) = {
// opposite order defined in class BB
implicit val ordering: Ordering[A] =
Ordering.by{ case bb: BB => bb.i }
Array[A](elems: _*).sorted
}
This version (below) give me an error...
def func3[A : Ordering : ClassTag](elems: A*) = {
// opposite order defined in class BB
implicit val ordering: Ordering[A] =
Ordering.by{ case bb: BB => bb.i }
Array[A](elems: _*).sorted
}
error: ambiguous implicit values: both value evidence$1 of type Ordering[A]
and value ordering of type Ordering[A] match expected type
scala.math.Ordering[A]
So based on this... I'm guessing : Ordering sort of converts Ordered[BB] into an implicit val ordering... or something like that? Are there deeper differences that my toy examples fail to reveal?
Thanks in advance.
A : after a type parameter is syntactic sugar for the declaration of implicit parameters. In this case this means that
def func1[A: Ordering: ClassTag](elems: A*) = Array[A](elems: _*).sorted
is the same as
def func1[A](elems: A*)(implicit ordering: Ordering[A], classTag: ClassTag[A]) = Array[A](elems: _*).sorted
On the other hand func2 is declaring a view bound (<%) from A to Ordered. Knowing this the compiler can summon a Ordering[Ordered] that is passed to the sorted method
The reason why the latest version of fun3 is not compiling is because you are providing 2 implicit Ordering[A] in the scope: the one declared as an implicit parameter of fun3 and the implicit val ordering. The compiler doesn't know which one to choose and it complains about it, you should remove one of them to fix it.
Anyway, it is not a good idea to introduce code about specific types in the implementation of these functions. That pattern matching in the creation of the val ordering will fail for any type that is not BB.
If your goal is to define a specific Ordering[BB] you can do that in the companion object of BB and then load it in the implicit scope of the caller function like this
class BB(val i: Int) {
override def toString: String = s"BB(${i})"
}
object BB {
implicit val ordering = Ordering.by[BB, Int](_.i)
val reverseOrdering = Ordering.by[BB, Int](-_.i)
}
Then when you try to order an BB it will pick the implicit ordering by default, but you could always overwrite it by doing
implicit val ord = BB.reverseOrdering
Seq[BB]().sorted
Can someone explain to me (or redirect to resources) why in this particular case the type tag is not "properly" generated:
class A(s: Seq[_]*)
def toto[T: TypeTag](p: Seq[T]): Seq[T] = {
println(typeTag[T].tpe)
p
}
val data = Seq( ("a", "a") )
val x = data.map(_._1)
new A(
toto(x),
toto(data.map(_._2)),
toto[String](data.map(_._2))
)
// output:
// java.lang.String
// Any
// String
As far as I understand, it seems that as my class A takes "untyped" (well with existential types) sequences, then the compiler does not bother generate the proper type tag when not required explicitly (though it does know the type of data.map(_._2) it still uses TypeTag[Any]... ). But it looks quite strange and I wondered if there was a more scientific explanation to this phenomenom.
Also, how can I force the compiler to generate a proper TypeTag[String] even if I don't want to create special variable (like this x variable above)?
Nice problem! I have an explanation, but I am not certain it's right (80%, let's say).
As very often with Scala type inference question, you need to be aware of expected types. In this case, all arguments of new A are typed with expected type Seq[_], which is the same as Seq[Any] because of covariance. So:
toto(data.map(_._2)) is typed with expected type Seq[Any]; data.map(_._2) is typed with expected type Seq[Any]. The signature of Seq#map is
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Seq[A], B, That]): That
so That is inferred based on the expected type and a suitable implicit bf is found. I am not actually sure if B is inferred to String or Any, but it probably doesn't matter.
In the val x = data.map(_._1), there is no expected type so B is inferred to String, an implicit bf is found based on A and B and then That is inferred from the complete type of bf.
toto(x) is typed with expected type Seq[Any]; x is typed with expected type Seq[Any], but it already has type Seq[String] and the expected type doesn't matter.
I would like to extend answer of #AlexeyRomanov by possible solution how to force compiler to evaluate specific type:
From here I took idea for forcing type difference:
sealed class =!=[A,B]
trait LowerPriorityImplicits {
implicit def equal[A]: =!=[A, A] = sys.error("should not be called")
}
object =!= extends LowerPriorityImplicits {
implicit def nequal[A,B](implicit same: A =:= B = null): =!=[A,B] =
if (same != null) sys.error("should not be called explicitly with same type")
else new =!=[A,B]
}
Now we can add limitation for parameter to toto:
class A(s: Seq[_]*)
def toto[T: TypeTag](p: Seq[T])(implicit guard: T =!= Any): Seq[T] = {
println(typeTag[T].tpe)
p
}
val data = Seq(("a", "a"))
val x = data.map(_._1)
new A(
toto(x),
toto(data.map(_._2)),
toto[String](data.map(_._2))
)
And output I have
java.lang.String
java.lang.String
String
I'm trying to describe the types which a case class contains.
import shapeless._
import shapeless.ops.hlist.LiftAll
trait Desc[T] {
def description: String
}
case class Foo(f: Int)
object Foo {
implicit val description: Desc[Foo] = new Desc[Foo] { val description = "foo" }
}
case class SomeCaseClass(f: Foo)
val gen = Generic[SomeCaseClass]
val lifted = implicitly[LiftAll[Desc, gen.Repr]].instances.toList
Gives me
could not find implicit value for parameter toTraversableAux: shapeless.ops.hlist.ToTraversable.Aux[shapeless.ops.hlist.LiftAll[Playground.this.Desc,Playground.this.gen.Repr]#Out,List,Lub]
not enough arguments for method toList: (implicit toTraversableAux: shapeless.ops.hlist.ToTraversable.Aux[shapeless.ops.hlist.LiftAll[Playground.this.Desc,Playground.this.gen.Repr]#Out,List,Lub])toTraversableAux.Out.
Unspecified value parameter toTraversableAux.
Scastie here: https://scastie.scala-lang.org/bXu71pMQQzCqrrsahVBkWA
When you summon an implicit instance with implicitly[LiftAll[Desc, gen.Repr]] then the dependent type Out of LiftAll is lost, so the compiler doesn't know which type exactly instances will return.
To work around this problem most typeclasses in Shapeless define an apply method in their companion object which does retain all dependent type information. It's the reason that you can use gen.Repr in a meaningful way after calling val gen = Generic[SomeCaseClass]. For some reason however LiftAll.apply was not implemented in this way. So that leaves you the option of implementing your own implicitly, or since you're using Shapeless anyway, use its the which is supposed to be a better implicitly.
scala> def impl[T <: AnyRef](implicit ev: T): ev.type = ev
impl: [T <: AnyRef](implicit ev: T)ev.type
scala> impl[LiftAll[Desc, gen.Repr]].instances.toList
res1: List[Desc[Foo]] = List(Foo$$anon$1#40b3708a)
scala> the[LiftAll[Desc, gen.Repr]].instances.toList
res2: List[Desc[Foo]] = List(Foo$$anon$1#40b3708a)
You can see the difference here in the inferred types that the REPL displays:
scala> impl[LiftAll[Desc, gen.Repr]]
res3: LiftAll.Aux[Desc,Foo :: HNil,Desc[Foo] :: HNil] = shapeless.ops.hlist$LiftAll$$anon$206#384d060c
scala> implicitly[LiftAll[Desc, gen.Repr]]
res4: LiftAll[Desc,gen.Repr] = shapeless.ops.hlist$LiftAll$$anon$206#30787774
I've been experimenting with implicit conversions, and I have a decent understanding of the 'enrich-my-libray' pattern that uses these. I tried to combine my understanding of basic implicits with the use of implicit evidence... But I'm misunderstanding something crucial, as shown by the method below:
import scala.language.implicitConversions
object Moo extends App {
case class FooInt(i: Int)
implicit def cvtInt(i: Int) : FooInt = FooInt(i)
implicit def cvtFoo(f: FooInt) : Int = f.i
class Pair[T, S](var first: T, var second: S) {
def swap(implicit ev: T =:= S, ev2: S =:= T) {
val temp = first
first = second
second = temp
}
def dump() = {
println("first is " + first)
println("second is " + second)
}
}
val x = new Pair(FooInt(200), 100)
x.dump
x.swap
x.dump
}
When I run the above method I get this error:
Error:(31, 5) Cannot prove that nodescala.Moo.FooInt =:= Int.
x.swap
^
I am puzzled because I would have thought that my in-scope implict conversion would be sufficient 'evidence' that Int's can be converted to FooInt's and vice versa. Thanks in advance for setting me straight on this !
UPDATE:
After being unconfused by Peter's excellent answer, below, the light bulb went on for me one good reason you would want to use implicit evidence in your API. I detail that in my own answer to this question (also below).
=:= checks if the two types are equal and FooInt and Int are definitely not equal, although there exist implicit conversion for values of these two types.
I would create a CanConvert type class which can convert an A into a B :
trait CanConvert[A, B] {
def convert(a: A): B
}
We can create type class instances to transform Int into FooInt and vise versa :
implicit val Int2FooInt = new CanConvert[Int, FooInt] {
def convert(i: Int) = FooInt(i)
}
implicit val FooInt2Int = new CanConvert[FooInt, Int] {
def convert(f: FooInt) = f.i
}
Now we can use CanConvert in our Pair.swap function :
class Pair[A, B](var a: A, var b: B) {
def swap(implicit a2b: CanConvert[A, B], b2a: CanConvert[B, A]) {
val temp = a
a = b2a.convert(b)
b = a2b.convert(temp)
}
override def toString = s"($a, $b)"
def dump(): Unit = println(this)
}
Which we can use as :
scala> val x = new Pair(FooInt(200), 100)
x: Pair[FooInt,Int] = (FooInt(200), 100)
scala> x.swap
scala> x.dump
(FooInt(100), 200)
A =:= B is not evidence that A can be converted to B. It is evidence that A can be cast to B. And you have no implicit evidence anywhere that Int can be cast to FooInt vice versa (for good reason ;).
What you are looking for is:
def swap(implicit ev: T => S, ev2: S => T) {
After working through this excercise I think I have a better understanding of WHY you'd want to use implicit evidence serves in your API.
Implicit evidence can be very useful when:
you have a type parameterized class that provides various methods
that act on the types given by the parameters, and
when one or more of those methods only make sense when additional
constraints are placed on parameterized types.
So, in the case of the simple API given in my original question:
class Pair[T, S](var first: T, var second: S) {
def swap(implicit ev: T =:= S, ev2: S =:= T) = ???
def dump() = ???
}
We have a type Pair, which keeps two things together, and we can always call dump() to examine the two things. We can also, under certain conditions, swap the positions of the first and second items in the pair. And those conditions are given by the implicit evidence constraints.
The Programming in Scala book gives a nice example of how this technique
is used in Scala collections, specifically on the toMap method of Traversables.
The book points out that Map's constructor
wants key-value pairs, i.e., two-tuples, as arguments. If we have a
sequence [Traversable] of pairs, wouldn’t it be nice to create a Map
out of them in one step? That’s what toMap does, but we have a
dilemma. We can’t allow the user to call toMap if the sequence is not
a sequence of pairs.
So there's an example of a type [Traversable] that has a method [toMap] that can't be used in all situations... It can only be used when the compiler can 'prove' (via implicit evidence) that the items in the Traversable are pairs.
I have a Number Wrapper like this
class NumWrapper[A<:AnyVal](var v: A)(implicit n:Numeric[A]) {
def +(other: A): NumWrapper[A] = {
new NumWrapper(n.plus(v, other))
}
def -(other: A): NumWrapper[A] = {
new NumWrapper(n.minus(v, other))
}
}
All work fine. But when I want to have the implicit conversion, i create a companion class as followed:
object NumWrapper {
implicit def toNumWrapper[A<:AnyVal](v: A) = new NumWrapper[A](v)
}
But I have the error at compilation:
could not find implicit value for parameter n: Numeric[A]
What is wrong here ? Why it is trying to find the implicit match for type A at compilation?
Thank you very much for your help.
Implicit checks in Scala are performed at compile time (it is a statically typed language). If the compiler can't identify a single, unambiguous, matching implicit value that will be available at the calling location, it complains.
One way you can fix this here is to add the implicit requirement to the toNumWrapper method:
object NumWrapper {
implicit def toNumWrapper[A<:AnyVal](v: A)(implicit n:Numeric[A]) = new NumWrapper[A](v)
}
This pushes the requirment for an implicit Numeric out to the location where the implicit conversion is required, eg, in the console, I could then write:
scala> val chk1 = 3L
chk1: Long = 3
scala> val chk2 = NumWrapper.toNumWrapper(chk1)
chk2: NumWrapper[Long] = NumWrapper#1e89017a
And the compiler is happy because (I think - not entirely sure of this) the Long value carries its own implicit Numeric[Long] with it.
According your code,
class NumWrapper[A<:AnyVal](var v: A)(implicit n:Numeric[A])
to call new NumWrapper[MyType](v) a Numeric[MyType] must be in the scope of implicit resolution.
So when you have
object NumWrapper {
implicit def toNumWrapper[A<:AnyVal](v: A) = new NumWrapper[A](v)
}
which is calling this NumWrapper constructor, the Numeric[A] must resolved. That's not the case and the compiler raise the mentioned error.