Pimps are not working when used with generics - scala

Consider following code (script) in which the SeqPimps can't be changed:
import scala.reflect.ClassTag
implicit class SeqPimps[T: ClassTag](s: Seq[T]) {
def indexOfOpt(e: T): Option[Int] = s.indexOf(e) match {
case -1 => None
case idx => Some(idx)
}
}
class A[T] {
val fn = (y: T) => List[T]().indexOfOpt(y)
}
object Main extends App {
val fn = (y: Int) => List[Int]().indexOfOpt(y)
println(fn(0))
println((new A[String]).fn(""))
}
Main.main(args)
It crashes with:
xxx/test.scala:11: error: value indexOfOpt is not a member of List[T]
val fn = (y: T) => List[T]().indexOfOpt(y)
^
one error found
My questions:
Why is it working when type is explicitly specified (in Main, after commenting out A and the one println it works fine) and complaining about non-existing member when generic type is used? The call looks same.
How to fix the snippet without modifying SeqPimps (e.g. removing of ClassTag - it is required by other methods in real project)?

Remember that writing class SeqPimps[T: ClassTag](s: Seq[T]) actually tells the compiler to add an implicit parameter like that: class SeqPimps[T](s: Seq[T])(implicit ev: ClassTag[T]).
The compilation fails because the implicit SeqPimps cannot be applied, and this one cannot be applied because no implicit ClassTag[T] is available from within A.
There are a couple ways you can add a ClassTag there, for example: class A[T : ClassTag] {. Where to pass that implicit ClassTag is up to you and your use case...

Oh, it turns out I was missing a ClassTag in class definition:
class A[T: ClassTag] {

Related

Scala TypeTag doesn't prevent from Type Erasure

In this thread, I'm writing a simple helper function for TraversableLike:
How to specify a type parameter in calling a function while let the compiler infer the other?
I implement the following function:
implicit class TraversableLikeView[A, Repr](self: TraversableLike[A, Repr]) {
def filterByType[B: TypeTag] = new FilterByType[B]
class FilterByType[B: TypeTag] {
def get[That](implicit bf: CanBuildFrom[Repr, B, That]): That = {
val result = self.flatMap{
v =>
val unboxed = Utils.javaUnbox(v)
unboxed match {
case x: B => Some(x)
case _ => None
}
}(bf)
result
}
}
}
The TypeTag is used since ClassTag.unapply had some problem in handling primitive classes. However, when I compile the above code I got the following warning:
Warning:(304, 23) abstract type pattern B is unchecked since it is eliminated by erasure
case x: B => Some(x)
^
Which is against what TypeTag claim to do (ClassTag was doing an almost perfect job here). Is there a reason why TypeTag fail in this case?
This is only supported by ClassTag, because you can get a Class from it and you can't in general get a Class from a TypeTag: e.g. in macros the class isn't compiled yet. But presumably you are using scala.reflect.runtime.universe.TypeTag, in which case you can write
implicit val classTagB = ClassTag[B](mirror.runtimeClass(typeTag[B].tpe))

Can I use a view bound in a Scala value class?

While dealing with some Java code, I wanted to find a way to reduce a Raw Set to include its parameterized type.
I also wanted it to work for Scala sets as well, so I did the following
implicit class Harden[S <% mutable.Set[_]](val set: S) extends AnyVal {
def cast[T] = set.map(_.asInstanceOf[T])
}
That resulted in a compiler error that I didn't expect
Error:(27, 27) field definition is not allowed in value class
implicit class Harden[S <% mutable.Set[_]](val set: S) extends AnyVal {
I didn't find any mention of this type of restriction in the Scala View Bounds or Value Class documentation.
Why is this not allowed? I'm using Scala 2.10.3.
As you can see from this sbt console output:
scala> :type implicit class Harden[S <% mutable.Set[_]](val set: S)
[S]AnyRef {
val set: S
private[this] val set: S
implicit private[this] val evidence$1: S => scala.collection.mutable.Set[_]
def <init>(set: S)(implicit evidence$1: S => scala.collection.mutable.Set[_]): Harden[S]
}
... the actual constructor of Harden desugars behind the scenes to:
def <init>(set: S)(implicit evidence$1: S => scala.collection.mutable.Set[_]): Harden[S]
... (i.e. takes set in one argument list and implicit evidence$1 in another).
As described in value classes limitations here:
must have only a primary constructor with exactly one public, val parameter whose type is not a value class.
... whitch means that Harden violaties this limitation.
You can achieve something similar, howerver. Try to convert your view bound defined on class to implicit evidence on method instead.
Something like this:
scala> implicit class Harden[S](val set: S) extends AnyVal {
| def cast[T](implicit ev: S => scala.collection.mutable.Set[_]) = set.map(_.asInstanceOf[T])
| }
defined class Harden
This will compile:
scala> Set(1,2,3).cast[Any]
res17: scala.collection.mutable.Set[Any] = Set(1, 2, 3)
And this will fail, as expected:
scala> List(1,2,3).cast[Any]
<console>:24: error: No implicit view available from List[Int] => scala.collection.mutable.Set[_].
List(1,2,3).cast[Any]
^
It is not allowed because as structured now, value classes must have exactly one parameter, but
implicit class Foo[A <% B](val a: A)
desugars to
implicit class Foo[A,B](val a: A)(implicit evidence$1: A => B)
which no longer has just a single parameter.

How to define a method that takes a heterogeneous sequence of objects of types belonging to a certain typeclass?

There is a type that can be parametrized by a certain restricted set of types:
trait Base[T] { def f(t: T): List[T] }
implicit object StringBase extends Base[String] {
override def f(t: String) = t.toList.map(c => String.valueOf(c))
}
implicit object IntBase extends Base[Int] {
override def f(t: Int) = List(t,t,t)
}
Now, I can define a function that takes a collection of a specific type and processes it:
def consume[T : Base](xs: Seq[T]) =
xs.map(x => implicitly[Base[T]].f(x).mkString("-"))
How do I define a function that takes a sequence of objects for types of which there exists an implicit conversion to Base and do the same? In a type-safe way, of course.
If I was not entirely clear, here's what I'd like to have:
consume(Seq(1,"asd", 3)) // => Seq("1-1-1", "a-s-d", "3-3-3")
I'm sure I can achieve it with shapeless' HList, but what about core Scala? Anyway, putting shapeless tag in case functionally inclined guys are willing to help.
import shapeless._
import ops.hlist.Mapper
import ops.hlist.ToList
trait Base[T] { def f(t: T): List[T] }
implicit object StringBase extends Base[String] {
override def f(t: String) = t.toList.map(c => String.valueOf(c))
}
implicit object IntBase extends Base[Int] {
override def f(t: Int) = List(t,t,t)
}
object base extends Poly1 {
implicit def forBase[A : Base] = at[A](x => implicitly[Base[A]].f(x))
}
def consume[T <: HList, Inter <: HList](xs: T)
(implicit
mapBase: Mapper.Aux[base.type, T, Inter],
interToList: ToList[Inter, List[Any]]): Seq[String] = {
xs.map(base).toList.map(_.mkString("-"))
}
Two key parts:
object base extends Poly1 : This is a polymorphic function only defined on types with a Base typeclass instance. It calls Base.f on its arg.
The implicits and type params in consume :
T is our input HList type. Inter is an intermediate type variable that is the output type of the result of mapping base over T.
mapBase: Mapper.Aux[base.type, T, Inter] : This is evidence that if we map base over T we get Inter. We need this to call .map on the incoming hlist. By putting it in our implicits list, we just require that it exists when the function is called. Shapeless will generate this for us if it can. If it can't, it most likely means that you forgot to define a Base instance for a type in T
interToList: ToList[Inter, List[Any]] : This is evidence that you can convert the HList Inter to a List[List[Any]]. So List[Any] must be the least-upperbound type of all the types in Inter. Once again, by putting it in the input implicits, we just require that shapeless can generate this for us. This is just boilerplate to prove to the compiler that we can call toList and get a List[List[Any]]. I haven't found a way to avoid this and the Inter variable in my experiences sadly.
Now thanks to all those implicits, we just call xs.map(base) to get an HList out with the appropriate Base.f applied. Then we call .toList to get a List[List[Any]]. Then we map over those List[Any]s and mkString with dashes as you wanted. And out comes our Seq[String]!
Here is it working in the REPL:
scala> consume(1 :: "asd" :: 3 :: HNil)
res0: Seq[String] = List(1-1-1, a-s-d, 3-3-3)
Here is dirty hack for consume method. Not super type safe and nice but may be fine as a workaround.
trait Base[T] { def f(t: T): List[T] }
implicit object StringBase extends Base[String] {
override def f(t: String) = t.toList.map(c => String.valueOf(c))
}
implicit object IntBase extends Base[Int] {
override def f(t: Int) = List(t,t,t)
}
case class Consumable[T](v: T, base: Base[T])
implicit def toConsumable[T](v: T)(implicit base: Base[T], ev: ClassTag[T]) =
Consumable(v, base)
def consume(xs: Consumable[_]*) =
xs.map(x => x.base.asInstanceOf[Base[Any]].f(x.v).mkString("-"))
println(consume(1, 2, 3))
println(consume("a", "b", "c"))
println(consume(1, 2, "a", "b", "c"))

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.
}

Scala double definition (2 methods have the same type erasure)

I wrote this in scala and it won't compile:
class TestDoubleDef{
def foo(p:List[String]) = {}
def foo(p:List[Int]) = {}
}
the compiler notify:
[error] double definition:
[error] method foo:(List[String])Unit and
[error] method foo:(List[Int])Unit at line 120
[error] have same type after erasure: (List)Unit
I know JVM has no native support for generics so I understand this error.
I could write wrappers for List[String] and List[Int] but I'm lazy :)
I'm doubtful but, is there another way expressing List[String] is not the same type than List[Int]?
Thanks.
I like Michael Krämer's idea to use implicits, but I think it can be applied more directly:
case class IntList(list: List[Int])
case class StringList(list: List[String])
implicit def il(list: List[Int]) = IntList(list)
implicit def sl(list: List[String]) = StringList(list)
def foo(i: IntList) { println("Int: " + i.list)}
def foo(s: StringList) { println("String: " + s.list)}
I think this is quite readable and straightforward.
[Update]
There is another easy way which seems to work:
def foo(p: List[String]) { println("Strings") }
def foo[X: ClassTag](p: List[Int]) { println("Ints") }
def foo[X: ClassTag, Y: ClassTag](p: List[Double]) { println("Doubles") }
For every version you need an additional type parameter, so this doesn't scale, but I think for three or four versions it's fine.
[Update 2]
For exactly two methods I found another nice trick:
def foo(list: => List[Int]) = { println("Int-List " + list)}
def foo(list: List[String]) = { println("String-List " + list)}
Instead of inventing dummy implicit values, you can use the DummyImplicit defined in Predef which seems to be made exactly for that:
class TestMultipleDef {
def foo(p:List[String]) = ()
def foo(p:List[Int])(implicit d: DummyImplicit) = ()
def foo(p:List[java.util.Date])(implicit d1: DummyImplicit, d2: DummyImplicit) = ()
}
To understand Michael Krämer's solution, it's necessary to recognize that the types of the implicit parameters are unimportant. What is important is that their types are distinct.
The following code works in the same way:
class TestDoubleDef {
object dummy1 { implicit val dummy: dummy1.type = this }
object dummy2 { implicit val dummy: dummy2.type = this }
def foo(p:List[String])(implicit d: dummy1.type) = {}
def foo(p:List[Int])(implicit d: dummy2.type) = {}
}
object App extends Application {
val a = new TestDoubleDef()
a.foo(1::2::Nil)
a.foo("a"::"b"::Nil)
}
At the bytecode level, both foo methods become two-argument methods since JVM bytecode knows nothing of implicit parameters or multiple parameter lists. At the callsite, the Scala compiler selects the appropriate foo method to call (and therefore the appropriate dummy object to pass in) by looking at the type of the list being passed in (which isn't erased until later).
While it's more verbose, this approach relieves the caller of the burden of supplying the implicit arguments. In fact, it even works if the dummyN objects are private to the TestDoubleDef class.
Due to the wonders of type erasure, the type parameters of your methods' List get erased during compilation, thus reducing both methods to the same signature, which is a compiler error.
As Viktor Klang already says, the generic type will be erased by the compiler. Fortunately, there's a workaround:
class TestDoubleDef{
def foo(p:List[String])(implicit ignore: String) = {}
def foo(p:List[Int])(implicit ignore: Int) = {}
}
object App extends Application {
implicit val x = 0
implicit val y = ""
val a = new A()
a.foo(1::2::Nil)
a.foo("a"::"b"::Nil)
}
Thanks for Michid for the tip!
If I combine Daniels response and Sandor Murakozis response here I get:
#annotation.implicitNotFound(msg = "Type ${T} not supported only Int and String accepted")
sealed abstract class Acceptable[T]; object Acceptable {
implicit object IntOk extends Acceptable[Int]
implicit object StringOk extends Acceptable[String]
}
class TestDoubleDef {
def foo[A : Acceptable : Manifest](p:List[A]) = {
val m = manifest[A]
if (m equals manifest[String]) {
println("String")
} else if (m equals manifest[Int]) {
println("Int")
}
}
}
I get a typesafe(ish) variant
scala> val a = new TestDoubleDef
a: TestDoubleDef = TestDoubleDef#f3cc05f
scala> a.foo(List(1,2,3))
Int
scala> a.foo(List("test","testa"))
String
scala> a.foo(List(1L,2L,3L))
<console>:21: error: Type Long not supported only Int and String accepted
a.foo(List(1L,2L,3L))
^
scala> a.foo("test")
<console>:9: error: type mismatch;
found : java.lang.String("test")
required: List[?]
a.foo("test")
^
The logic may also be included in the type class as such (thanks to jsuereth):
#annotation.implicitNotFound(msg = "Foo does not support ${T} only Int and String accepted")
sealed trait Foo[T] { def apply(list : List[T]) : Unit }
object Foo {
implicit def stringImpl = new Foo[String] {
def apply(list : List[String]) = println("String")
}
implicit def intImpl = new Foo[Int] {
def apply(list : List[Int]) = println("Int")
}
}
def foo[A : Foo](x : List[A]) = implicitly[Foo[A]].apply(x)
Which gives:
scala> #annotation.implicitNotFound(msg = "Foo does not support ${T} only Int and String accepted")
| sealed trait Foo[T] { def apply(list : List[T]) : Unit }; object Foo {
| implicit def stringImpl = new Foo[String] {
| def apply(list : List[String]) = println("String")
| }
| implicit def intImpl = new Foo[Int] {
| def apply(list : List[Int]) = println("Int")
| }
| } ; def foo[A : Foo](x : List[A]) = implicitly[Foo[A]].apply(x)
defined trait Foo
defined module Foo
foo: [A](x: List[A])(implicit evidence$1: Foo[A])Unit
scala> foo(1)
<console>:8: error: type mismatch;
found : Int(1)
required: List[?]
foo(1)
^
scala> foo(List(1,2,3))
Int
scala> foo(List("a","b","c"))
String
scala> foo(List(1.0))
<console>:32: error: Foo does not support Double only Int and String accepted
foo(List(1.0))
^
Note that we have to write implicitly[Foo[A]].apply(x) since the compiler thinks that implicitly[Foo[A]](x) means that we call implicitly with parameters.
There is (at least one) another way, even if it is not too nice and not really type safe:
import scala.reflect.Manifest
object Reified {
def foo[T](p:List[T])(implicit m: Manifest[T]) = {
def stringList(l: List[String]) {
println("Strings")
}
def intList(l: List[Int]) {
println("Ints")
}
val StringClass = classOf[String]
val IntClass = classOf[Int]
m.erasure match {
case StringClass => stringList(p.asInstanceOf[List[String]])
case IntClass => intList(p.asInstanceOf[List[Int]])
case _ => error("???")
}
}
def main(args: Array[String]) {
foo(List("String"))
foo(List(1, 2, 3))
}
}
The implicit manifest paramenter can be used to "reify" the erased type and thus hack around erasure. You can learn a bit more about it in many blog posts,e.g. this one.
What happens is that the manifest param can give you back what T was before erasure. Then a simple dispatch based on T to the various real implementation does the rest.
Probably there is a nicer way to do the pattern matching, but I haven't seen it yet. What people usually do is matching on m.toString, but I think keeping classes is a bit cleaner (even if it's a bit more verbose). Unfortunately the documentation of Manifest is not too detailed, maybe it also has something that could simplify it.
A big disadvantage of it is that it's not really type safe: foo will be happy with any T, if you can't handle it you will have a problem. I guess it could be worked around with some constraints on T, but it would further complicate it.
And of course this whole stuff is also not too nice, I'm not sure if it worth doing it, especially if you are lazy ;-)
Instead of using manifests you could also use dispatchers objects implicitly imported in a similar manner. I blogged about this before manifests came up: http://michid.wordpress.com/code/implicit-double-dispatch-revisited/
This has the advantage of type safety: the overloaded method will only be callable for types which have dispatchers imported into the current scope.
Nice trick I've found from http://scala-programming-language.1934581.n4.nabble.com/disambiguation-of-double-definition-resulting-from-generic-type-erasure-td2327664.html
by Aaron Novstrup
Beating this dead horse some more...
It occurred to me that a cleaner hack is to use a unique dummy type
for each method with erased types in its signature:
object Baz {
private object dummy1 { implicit val dummy: dummy1.type = this }
private object dummy2 { implicit val dummy: dummy2.type = this }
def foo(xs: String*)(implicit e: dummy1.type) = 1
def foo(xs: Int*)(implicit e: dummy2.type) = 2
}
[...]
I tried improving on Aaron Novstrup’s and Leo’s answers to make one set of standard evidence objects importable and more terse.
final object ErasureEvidence {
class E1 private[ErasureEvidence]()
class E2 private[ErasureEvidence]()
implicit final val e1 = new E1
implicit final val e2 = new E2
}
import ErasureEvidence._
class Baz {
def foo(xs: String*)(implicit e:E1) = 1
def foo(xs: Int*)(implicit e:E2) = 2
}
But that will cause the compiler to complain that there are ambiguous choices for the implicit value when foo calls another method which requires an implicit parameter of the same type.
Thus I offer only the following which is more terse in some cases. And this improvement works with value classes (those that extend AnyVal).
final object ErasureEvidence {
class E1[T] private[ErasureEvidence]()
class E2[T] private[ErasureEvidence]()
implicit def e1[T] = new E1[T]
implicit def e2[T] = new E2[T]
}
import ErasureEvidence._
class Baz {
def foo(xs: String*)(implicit e:E1[Baz]) = 1
def foo(xs: Int*)(implicit e:E2[Baz]) = 2
}
If the containing type name is rather long, declare an inner trait to make it more terse.
class Supercalifragilisticexpialidocious[A,B,C,D,E,F,G,H,I,J,K,L,M] {
private trait E
def foo(xs: String*)(implicit e:E1[E]) = 1
def foo(xs: Int*)(implicit e:E2[E]) = 2
}
However, value classes do not allow inner traits, classes, nor objects. Thus also note Aaron Novstrup’s and Leo’s answers do not work with a value classes.
I didn't test this, but why wouldn't an upper bound work?
def foo[T <: String](s: List[T]) { println("Strings: " + s) }
def foo[T <: Int](i: List[T]) { println("Ints: " + i) }
Does the erasure translation to change from foo( List[Any] s ) twice, to foo( List[String] s ) and foo( List[Int] i ):
http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ108
I think I read that in version 2.8, the upper bounds are now encoded that way, instead of always an Any.
To overload on covariant types, use an invariant bound (is there such a syntax in Scala?...ah I think there isn't, but take the following as conceptual addendum to the main solution above):
def foo[T : String](s: List[T]) { println("Strings: " + s) }
def foo[T : String2](s: List[T]) { println("String2s: " + s) }
then I presume the implicit casting is eliminated in the erased version of the code.
UPDATE: The problem is that JVM erases more type information on method signatures than is "necessary". I provided a link. It erases type variables from type constructors, even the concrete bound of those type variables. There is a conceptual distinction, because there is no conceptual non-reified advantage to erasing the function's type bound, as it is known at compile-time and does not vary with any instance of the generic, and it is necessary for callers to not call the function with types that do not conform to the type bound, so how can the JVM enforce the type bound if it is erased? Well one link says the type bound is retained in metadata which compilers are supposed to access. And this explains why using type bounds doesn't enable overloading. It also means that JVM is a wide open security hole since type bounded methods can be called without type bounds (yikes!), so excuse me for assuming the JVM designers wouldn't do such an insecure thing.
At the time I wrote this, I didn't understand that stackoverflow was a system of rating people by quality of answers like some competition over reputation. I thought it was a place to share information. At the time I wrote this, I was comparing reified and non-reified from a conceptual level (comparing many different languages), and so in my mind it didn't make any sense to erase the type bound.