Scala: Implictly convert a list - scala

Here is a reduced example of what I want to do. The line commented out doesn't compile.
class Animal
object Animal { implicit def toElephant(a: Animal) = a.asInstanceOf[Elephant] }
class Elephant extends Animal
object Main {
def main(args: Array[String]) = {
val a: List[Animal] = List(new Elephant, new Elephant)
// val e: List[Elephant] = a
}
}
In a regular situation, e = a is of course illegal. But with the implicit function, one could think that scala would automatically convert every element in the list.
Is there an elegant way to get this behaviour? If yes, how?
What I wish to know is if there is some obscure corner of scala that can force the behaviour I wish. I am not interested in solutions that add cruft. I can think of them myself. For instance, one could do:
object Animal {
implicit def toElephant(a: Animal) = a.asInstanceOf[Elephant]
implicit def toElephant(a: List[Animal]) = a.asInstanceOf[List[Elephant]] }
and the code above would work.

You can forget implicits and mapping and use simply
val e = a.asInstanceOf[List[Elephant]]
BUT, if you insist, you can of course also do this conversion implicitly. Having an implicit from List[A] to List[B] is no more crufty than an implicit A => B. I wouldn't do this, but if I did I'd generalise it for re-use, importing locally to limit the implicit's scope:
object Implicits {
implicit def AListToBList[A, B <: A](lst: List[A]) = lst.asInstanceOf[List[B]]
}
Then at use-site
import Implicits._
val a: List[Animal] = List(new Elephant, new Elephant)
val e: List[Elephant] = a
e.head.doSomethingElephanty
Be aware of the scope of the import, and stick things within a locally block if necessary.

But with the implicit function, one could think that scala would
automatically convert every element in the list.
Why?
Let's try something:
class X[T : Manifest] {
override def toString = manifest[T].toString
}
val x = new X[Animal]
How will an implicit that converts Animal into Elephant help convert an X[Animal] into an X[Elephant]? There isn't even an instance of Animal to be converted! But let's put an instance there:
class X[T : Manifest](t: T) {
override def toString = manifest[T].toString + t.toString
}
Now we have an instance, but, again, how will Scala convert an X[Animal] into an X[Elephant]? It can't even get at t, because it is private. Let's make it public, then:
class X[T : Manifest](val t: T) {
override def toString = manifest[T].toString + t.toString
}
There, it is public. But how would it be converted? One way would be this:
new X[Elephant](Animal toElephant x.t)
But how would Scala know to do that? Who says that's valid code, or that it is enough?
One could write an implicit teaching X how to convert itself if another implicit conversion is present, and an implicit like that could exist for List, but implicit conversions are dangerous. The less of them there are, the better. And, therefore, such an implicit does not exist.

What about map?
val e = a map {_.asInstanceOf[Elephant]}
or even better:
val e = a collect {case e: Elephant => e}
Note that both asInstanceOf and an implicit conversion for super-type to sub-type is not very ellegant.

Related

Is there any way of calling scala method (having type parameter ) with infix notation

I have a piece of code in implicit class -
implicit class Path(bSONValue: BSONValue) {
def |<[S, T <:{def value:S}] = {
bSONValue.asInstanceOf[T].value
}
}
The problem is if I want to call |< method after BSONValue I need to call with . .
e.g
(doc/"_id").|<[String,BSONString]
The problem is without . scala raises error because it does not allow type parameter method with infix notation. So always I have to wrap doc/"_id" portion with ().
Is their any way of using type parameter method without . eg
doc/"_id"|<[String,BSONString]
All types T that you want to get out of BSONValues will probably have a companion object with the same name. You could use that companion object as an intuitive placeholder for the type that you actually want to get. Something along these lines:
trait Extract[A, BComp, B] {
def extractValue(a: A): B
}
implicit class Extractable[A](a: A) {
def |<[BC, B]
(companion: BC)
(implicit e: Extract[A, BC, B])
: B = e.extractValue(a)
}
implicit def extractIntFromString
: Extract[String, Int.type, Int] = _.toInt
implicit def extractDoubleFromString
: Extract[String, Double.type, Double] = _.toDouble
val answer = "42" |< Int
val bnswer = "42.1" |< Double
This allows you to use infix syntax, because all those things are ordinary values.
Still, only because it's possible, it doesn't mean that you have to do it.
For instance, I wouldn't know what to expect from a |<-operator.
Many other people also wouldn't know what to do with it.
They'd have to go and look it up. Then they would see this signature:
def |<[BC, B](companion: BC)(implicit e: Extract[A, BC, B]): B
I can imagine that the vast majority of people (myself in one week included) would not be immediately enlightened by this signature.
Maybe you could consider something more lightweight:
type BSONValue = String
trait Extract[B] {
def extractValue(bsonValue: BSONValue): B
}
def extract[B](bson: BSONValue)(implicit efb: Extract[B])
: B = efb.extractValue(bson)
implicit def extractIntFromString
: Extract[Int] = _.toInt
implicit def extractDoubleFromString
: Extract[Double] = _.toDouble
val answer = extract[Int]("42")
val bnswer = extract[Double]("42.1")
println(answer)
println(bnswer)
It seems to do roughly the same as the |< operator, but with much less magic going on.

scala polymorphic type signatures with Ordering and ClassTag

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

Scala: Implicit evidence for generic types

Assume there are such two traits:
trait Fooer[-T] {
def foo(x: T): Unit
}
trait CanFoo[-T] {
def fooer: Fooer[T]
}
And a function:
def bar[T: CanFoo](x: T) = {
implicitly[CanFoo[T]].fooer.foo(x)
}
Everything works so far. However, I was stuck when trying to make bar work recursively on collection types like Seq[T] (i.e. bar[Seq[T]](seq) recursively calls bar[T] on seq's elements). I can't do implicit object CanFooSeq extends CanFoo[Seq[_]] since that would cause the type information of the elements to be lost. (I also tried to make another function def bar[T: CanFoo](seq: Seq[T]) = ..., but that didn't solve the problem either since Seq[T] still isn't being recognized as a Foo-able type.)
Is there any way to solve this problem?
implicit def CanFooSeq[T]: CanFoo[Seq[T]] = new CanFoo[Seq[T]] { def fooer = ... }
(if you want to have it only in case you have CanFoo[T], add the implicit parameter: implicit def CanFooSeq[T: CanFoo]: CanFoo[Seq[T]] = new CanFoo[Seq[T]] { def fooer = ... }) if I understood the question correctly. Note it has to be a def, because objects and vals can't have type parameters, so a new one will be created on each call (which is very unlikely to matter for performance in practice).

Could not find implicit parameter in companion class

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.

Typeclass instances for unnamed types in Scala

How would one encode the following constraint in Scala (pseudocode)?
def foo(x: T forSome { type T has a Numeric[T] instance in scope }) = {
val n= implicitly[...] // obtain the Numeric instance for x
n.negate(x) // and use it with x
}
In words: I need a type class instance for my input argument, but I don't care about the argument's type, I just need to obtain the instance and use it on my argument.
It doesn't have to be an existential type, but I need to avoid type parameters in the def's signature.
Edit: just to clarify, the standard approach in these cases, i.e.:
def foo[T: Numeric](x: T) = ...
doesn't work for me, as it requires the addition of a type parameter on the method.
Thanks.
I managed to make it work like this:
implicit class InstanceWithNumeric[T](val inst: T)(implicit val n: Numeric[T])
def foo(iwn: InstanceWithNumeric[_]) {
def genFoo[T](iwn: InstanceWithNumeric[T]) {
println(iwn.n.negate(iwn.inst))
}
genFoo(iwn)
}
And now:
scala> foo(1)
-1
scala> foo(1.2)
-1.2
Not the prettiest, but seems to work.
EDIT: You can avoid defining inner function like this:
implicit class InstanceWithNumeric[T](val inst: T)(implicit val n: Numeric[T]) {
def negate = n.negate(inst)
}
Also, if you want to make implicit conversion to InstanceWithNumeric globally visible, you can do something like this:
class InstanceWithNumeric[T](val inst: T)(implicit val n: Numeric[T])
object InstanceWithNumeric {
implicit def apply[T: Numeric](inst: T) =
new InstanceWithNumeric(inst)
}
If you want to understand how this works, read about so called implicit scope (this question seems to contain good explanation).
Not quite sure what you are attempting, because it seems you need a type once you make the call to implicitly. Would the following work for you?
def foo(implicit x: Numeric[_]) {
//code goes here.
}