1

In scala language, the implicit scope of a class is erased in runtime, e.g. if defining:

case class A(i: Int)

object A {

  implicit def toInt(a: A) = a.i
}

Then for an array:

val arr = Array[Any](A(1), 2)

it is impossible to write:

arr.map(_ + 3)

as type A and its implicit scope is removed after being inserted to Array[Any].

This makes some design patterns (e.g. type class lookup) impossible to be applied in runtime (when type information is still partially available). In my case, I would like to write the above program without explicitly stating A in type matching (as in real case the number of classes like A can be countless). Is any scala metaprogramming package (scalameta preferred) capable of doing this in one project? What should I do to tell the Java runtime bytecode to "look for implicit for a runtime class, if not found do something else"?

tribbloid
  • 4,026
  • 14
  • 64
  • 103
  • 4
    This problem has nothing to do with type erasure. It has to do with the simple fact that `Any` has no implicit conversion to `Int`. You're not checking for conversions from `A` to `Int` because `A` isn't the type of elements in the array. – Silvio Mayolo Dec 28 '17 at 00:24
  • @tribbloid, I doubt your last claim about the type of `arr.head.getClass.getSimpleName` in the code as you provided in your question. You can easily [see yourself](https://scastie.scala-lang.org/ge87lTftTcOWyhnA6XuzSw) that it is actually `A` (and the second `Int` is wrapped into `Integer`-object type). It becomes `Int` if you declare your array as `Array[Int]`, but then your `map` also compiles. So you probably should provide a more realistic example of your problem. – SergGr Dec 28 '17 at 04:07
  • @SergGr Err, sorry my mistake, fixing immediately: except that the runtime type is not 'Any': arr.head.getClass.getSimpleName == "A" – tribbloid Dec 28 '17 at 04:28
  • @tribbloid, but then Silvio is right - the trouble is not related to type erasure at all. Even if there were no type erasure in Scala/Java, since you have `Array[Any]` what `map` gets as its input must have type `Any` and you have to provide a function that can handle any value of the type `Any` i.e. any value at all. To put it otherwise, what behavior you expect from that "magic library" if you actually put something like `Thread` into your `Array[Any]`? – SergGr Dec 28 '17 at 04:33
  • @SergGr you are right, removing JVM type erasure doesn't solve my problem, the problem is only about making implicit for a type referable in both phases. – tribbloid Dec 28 '17 at 18:07
  • @SergGr for your second question, I already gave an answer at the end of the question: when an implicit, e.g. type class, for a runtime type exists, use it, otherwise do something else or throw a MatchException. In FP world this is a perfectly justifiable pattern. – tribbloid Dec 29 '17 at 01:57
  • @tribbloid, I wonder which exactly FP-world you mean when you say that "_throw a MatchException ... is a perfectly justifiable pattern_" in such case. Fundamentally I don't think it can be done in Scala because Scala is a very safe statically typed language and implicits were designed as static (i.e. compile time) feature as well. Particularly it means that implicit resolution happens at the compile-time and I don't think you can change it. The only ways around I can think of are either changing type to something more complicated than `Array[Any]` or using pattern matching inside `map` – SergGr Dec 29 '17 at 02:10
  • Particularly I don't think that from any standard Scala meta-programming tool you can generate something that is based on getting the list all the types that has implicit variables of a given shape visible in this particular place in the code. The list of the types has to come from somewhere outside. – SergGr Dec 29 '17 at 02:14
  • @SergGr are you suggesting that in a type-safe FP language, finding a type class for a type can be safe in compilation, but unsafe in runtime? I know JVM has limitations like static bytecode and type erasure, but that's why I'm asking for using metaprogramming in a verbose way. – tribbloid Dec 29 '17 at 02:37
  • @SergGr If it is missing in scalameta then hope this feature can be added later. I mean, both type class and runtime algebraic pattern matching are good FP, but if they can't co-exist then they have room for improvements. – tribbloid Dec 29 '17 at 02:41
  • @tribbloid, 1) In no way you show that all values in the array are of the same type class. You can try to go this route but this would mean changing the type of the array to something more complicated than `Array[Any]`. 2) I'm not that familiar with other languages but AFAIU in Scala TypeClasses are implemented in a way that you can (using implicits) provide difference evidences that some class is a member of a given type class and get different behaviors. And this is probably something you often want e.g. for TC such a `Ordering`. However this means there is no "one canonical TC" for a class. – SergGr Dec 29 '17 at 02:51
  • @SergGr 'some class is a member of a given type class and get different behaviours' is also the point of pattern matching: you don't know the type (as in Array[Any]) but still can handle them with 'different behaviours' based on their runtime signature, it is not 'one canonical TC'. But obviously such feature would be very hard to write, maybe type class deserve some special treatment by the compiler. – tribbloid Dec 29 '17 at 04:51
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/162137/discussion-between-serggr-and-tribbloid). – SergGr Dec 29 '17 at 04:54

0 Answers0