I want to use sttp library with guice(with scalaguice wrapper) in my app. But seems it is not so easy to correctly bind things like SttpBackend[Try, Nothing]
SttpBackend.scala
Try[_] and Try[AnyRef] show some other errors, but still have no idea how it should be done correctly
the error I got:
kinds of the type arguments (scala.util.Try) do not conform to the expected kinds of the type parameters (type T).
[error] scala.util.Try's type parameters do not match type T's expected parameters:
[error] class Try has one type parameter, but type T has none
[error] bind[SttpBackend[Try, Nothing]].toProvider[SttpBackendProvider]
[error] ` ^
SttpBackendProvider looks like:
def get: SttpBackend[Try, Nothing] = TryHttpURLConnectionBackend(opts)
complete example in scastie
interesting that version scalaguice 4.1.0 show this error, but latest 4.2.2 shows error inside it with converting Nothing to JavaType
I believe you hit two different bugs in the Scala-Guice one of which is not fixed yet (and probably even not submitted yet).
To describe those issues I need a fast intro into how Guice and Scala-Guice work. Essentially what Guice do is have a mapping from type onto the factory method for an object of that type. To support some advanced features types are mapped onto some internal "keys" representation and then for each "key" Guice builds a way to construct a corresponding object. Also it is important that generics in Java are implemented using type erasure. That's why when you write something like:
bind(classOf[SttpBackend[Try, Nothing]]).toProvider(classOf[SttpBackendProvider])
in raw-Guice, the "key" actually becomes something like "com.softwaremill.sttp.SttpBackend". Luckily Guice developers have thought about this issue with generics and introduced TypeLiteral[T] so you can convey the information about generics.
Scala type system is more reach than in Java and it has some better reflection support from the compiler. Scala-Guice exploits it to map Scala-types on those more detailed keys automatically. Unfortunately it doesn't always work perfectly.
The first issue is the result of the facts that the type SttpBackend is defined as
trait SttpBackend[R[_], -S]
so it uses it expects its first parameter to be a type constructor; and that originally Scala-Guice used the scala.reflect.Manifest infrastructure. AFAIU such higher-kind types are not representable as Manifest and this is what the error in your question really says.
Luckily Scala has added a new scala.reflect.runtime.universe.TypeTag infrastructure to tackle this issue in a better and more consistent way and the Scala-Guice migrated to its usage. That's why with the newer version of Scala-Guice the compiler error goes away. Unfortunately there is another bug in the Scala-Guice that makes the code fail in runtime and it is a lack of handling of the Nothing Scala type. You see, the Nothing type is a kind of fake one on the JVM. It is one of the things where the Scala type system is more reach than the Java one. There is no direct mapping for Nothing in the JVM world. Luckily there is no way to create any value of the type Nothing. Unfortunately you still can create a classOf[Nothing]. The Scala-to-JVM compiler handles it by using an artificial scala.runtime.Nothing$. It is not a part of the public API, it is implementation details of specifically Scala over JVM. Anyway this means that the Nothing type needs additional handling when converting into the Guice TypeLiteral and there is none. There is for Any the cousin of Nothing but not for Nothing (see the usage of the anyType in TypeConversions.scala).
So there are really two workarounds:
Use raw Java-based syntax for Guice instead of the nice Scala-Guice one:
bind(new TypeLiteral[SttpBackend[Try, Nothing]]() {})
.toInstance(sttpBackend) // or to whatever
See online demo based on your example.
Patch the TypeConversions.scala in the Scala-Guice as in:
private[scalaguice] object TypeConversions {
private val mirror = runtimeMirror(getClass.getClassLoader)
private val anyType = typeOf[Any]
private val nothingType = typeOf[Nothing] // added
...
def scalaTypeToJavaType(scalaType: ScalaType): JavaType = {
scalaType.dealias match {
case `anyType` => classOf[java.lang.Object]
case `nothingType` => classOf[scala.runtime.Nothing$] //added
...
I tried it locally and it seems to fix your example. I didn't do any extensive tests so it might have broken something else.
Related
I'm still a bit confused about the scala Shapeless library after reading many articles. It seems that Shapeless uses scala compiling features? So does it use reflection and is it safe for production code?
Shapeless doesn't use reflection, it uses macros to inspect the structure of classes. With Shapeless this inspection happens at compilation time and not runtime (reflection happens at runtime). As a result of this Shapeless can be considered safer than reflection because it will be able to make many checks at compilation time.
Let's try to get a field by name using shapeless
case class MyClass(field: String)
import shapeless._
val myClassLens = lens[MyClass] >> 'field
val res = myClassLens.get(MyClass("value")) // res == "value"
if we use an invalid field name the compiler will complain with a compilation error
On the other hand if we tried to achieve this same thing using reflection the field name would be checked at runtime (maybe in production), that's why reflection is not considered as safe as Shapeless. It will also be way faster with Shapeless than reflection
I have a actor message of the following type:
case class RetrieveEntities[A](func:(Vector[A]) => Vector[A])
I then would like to handle the message in the following way:
def receive = {
case RetrieveEntities(parameters, func) =>
context.become(retrieveEntities(func))
def retrieveEntities(func:(Vector[T]) => Vector[T])(implicit mf: Manifest[T]){
case _ => ...
}
And I instantiate the actor in the following way:
TestActorRef(new RetrieveEntitiesService[Picture])
The problem is I receive the following compiler error:
type mismatch;
[error] found : Vector[Any] => Vector[Any]
[error] required: Vector[T] => Vector[T]
[error] context.become(retrieveEntities(func))
Which I suppose means I lost the type information but I am unsure why and how to prevent it.
Your example code is a bit to short to give you a solution, but from what you show it seems like what you are trying to do is not possible.
This is why
In Scala (and Java) the type parameters are erased, which means they disappear after compilation, so during runtime they are no longer available. This means that your pattern match on RetrieveEntities(parameters, func) is really a match where A can be anything. You then go on and call a method that is typed with T and there is no way for the compiler to know what you mean with that.
Manifest (which is deprecated), TypeTag and ClassTag are a mechanism that tells the compiler to create an object that provides type information for those after compilation but you have to "save" that information.
To be able to know what A you typed your RetrieveEntitiesService with you would need to take an implicit ClassTag to the constructor to base any logic on it (since when calling the constructor is the time that you know what A is):
import scala.reflect.ClassTag
case class RetrieveEntities[A](func:(Vector[A]) => Vector[A])(implicit val tag: ClassTag[A])
You could then call runtimeClass on the tag to get the type of A:
scala> val retrieve = RetrieveEntities[String](identity)
scala> retrieve.tag.runtimeClass
res2: Class[_] = class java.lang.String
Note that this still would not let you type a method call with since we are now in runtime, but it would let you use that instance of Class to compare with the runtimeClass of E of the actor and then do a safe cast to RetrieveEntities[E] if you like. (and also regular runtime conditional flows, reflection etc.).
Two important notes before you start doing that
I would not advice you to go down that path until you are more confident with the type system and really really know that there is no other reasonable design that solves your problem. Again I can not help you towards such a solution with the sparse example code given. (Maybe your actor does not really need to know about the type of A for example, or there is a limited set of E:s that you might match on with concrete types)
As an additional warning, type and class tags are not thread safe in Scala 2.10, and might not be safe in 2.11 either, so mixing them with actors might be a bad idea. (http://docs.scala-lang.org/overviews/reflection/thread-safety.html)
johanandren's answer was certainly helpful, but at the end I found a way that it could compile and it is working for now.
I needed to give the compiler a more precise type annotation to make it work:
case RetrieveEntities(parameters, func:(Vector[T]) => Vector[T])
I still will continue to use Manifest instead of the new Reflection API (TypeTag and ClassTag) mainly because the library I am using (json4s) uses internally also the Manifest implementation, and I assume it will lead to less problems this way.
The following snippet returns true as expected:
import scala.reflect.runtime.universe._
typeOf[Seq[Int]] <:< typeOf[Traversable[Int]]
This snippet does not however:
val s = Seq[Int](1,2,3)
val m = runtimeMirror(this.getClass.getClassLoader)
val t = m.reflect(s).symbol.typeSignature
t <:< typeOf[Seq[Int]]
I'm sure that I'm just missing something obvious, but I have been on the REPL for a couple of hours and haven't worked it out. Any suggestions would be much appreciated. Thanks in advance.
1) typeOf[...] preserves the exact Scala type from Java erasure, however, obj.getClass (and consequently m.reflect(obj), which uses getClass under the covers) does not. Consequently, the best runtime reflection can get from reflecting on s without extra compile-time efforts is Seq[_] (which will fail the subtyping test). If you need to remember the exact Scala type of something for runtime, use type tags (just like typeOf does) or macros (just like type tags do).
2) .symbol.typeSignature isn't going to work, because that's ClassInfoType (i.e. a type, which encapsulates a list of parents and members of a class type). Class info types work great for inspecting members (probably also for base classes and maybe for a few more things as well, but I'm not sure off the top of my head), but not so great for everything else. You'd want to go for something like .symbol.asType.toType, which would return a TypeRef (i.e. in our case scala.collection.immutable.:: - note the lack of any type arguments here!). Unfortunately that'd still not work out of the box because of erasure as described in #1.
You don't need reflection to ascertain that a given value conforms to a given statically known type. There are two ways (at least) to do so:
if (someValue.isInstanceOf[SomeType])
...
else
...
or
someValue match {
case st: SomeType => ...
case _ =>
}
So I'm playing with writing a battlecode player in Scala. In battlecode certain classes are disallowed and there is a runtime exception if you ever try to access them. When I use the Array.fill function I get a message from the battlecode server saying [java] Illegal class: scala/reflect/Manifest$. This is the offending line:
val g_score = Array.fill[Int](rc.getMapWidth(), rc.getMapHeight())(0)
The method takes an implicit ClassManifest argument which has the following documentation:
A ClassManifest[T] is an opaque descriptor for type T. It is used by the compiler
to preserve information necessary for instantiating Arrays in those cases where
the element type is unknown at compile time.
But I do know the type of the array elements at compile time, as shown above I explicitly state that they will be Int. Is there a way to avoid this? To workaround I've written my own version of Array.fill. This seems like a hack. As an aside, does Scala have real 2D arrays? Array.fill seems to return an Array[Array[T]] which is the only way I found to write my own. This also seems inelegant.
Edit: Using Scala 2.9.1
For background information, see this related question: What is a Manifest in Scala and when do you need it?. In this answer, you will find an explanation why manifests are needed for arrays.
In short: Although the JVM uses type erasure, arrays are an exception and need a manifest. Since you could compile your code, that manifest was found (manifests are always available for proper types). Your error occurs at runtime.
I don't know the details of the battlecode server, but there are two possibilities: Either you are running your compiled classes with a binary incompatible version of Scala (difference in major version, e.g. compiled with Scala 2.9 and server uses 2.10). Or the server doesn't even have the scala-library.jar on its class path.
As said in the comment, manifests are deprecated in Scala 2.10 and replaced by ClassTag.
EDIT: So it seems the class loader is artificially restricting the allowed classes. My suggestion would be: Add a helper Java class. You can easily mix Java and Scala code. If it's just about the Int-Array instantiation, you could provide something like:
public static class Helper {
public static int[][] makeArray(int d1, int d2) { return new int[d1][d2](); }
}
(hope that's valid java code, a bit rusty)
Also, have you tried to create the outer array with new Array[Array[Int]](d1), and then iterate to create the inner arrays?
In groovy one can do:
class Foo {
Integer a,b
}
Map map = [a:1,b:2]
def foo = new Foo(map) // map expanded, object created
I understand that Scala is not in any sense of the word, Groovy, but am wondering if map expansion in this context is supported
Simplistically, I tried and failed with:
case class Foo(a:Int, b:Int)
val map = Map("a"-> 1, "b"-> 2)
Foo(map: _*) // no dice, always applied to first property
A related thread that shows possible solutions to the problem.
Now, from what I've been able to dig up, as of Scala 2.9.1 at least, reflection in regard to case classes is basically a no-op. The net effect then appears to be that one is forced into some form of manual object creation, which, given the power of Scala, is somewhat ironic.
I should mention that the use case involves the servlet request parameters map. Specifically, using Lift, Play, Spray, Scalatra, etc., I would like to take the sanitized params map (filtered via routing layer) and bind it to a target case class instance without needing to manually create the object, nor specify its types. This would require "reliable" reflection and implicits like "str2Date" to handle type conversion errors.
Perhaps in 2.10 with the new reflection library, implementing the above will be cake. Only 2 months into Scala, so just scratching the surface; I do not see any straightforward way to pull this off right now (for seasoned Scala developers, maybe doable)
Well, the good news is that Scala's Product interface, implemented by all case classes, actually doesn't make this very hard to do. I'm the author of a Scala serialization library called Salat that supplies some utilities for using pickled Scala signatures to get typed field information
https://github.com/novus/salat - check out some of the utilities in the salat-util package.
Actually, I think this is something that Salat should do - what a good idea.
Re: D.C. Sobral's point about the impossibility of verifying params at compile time - point taken, but in practice this should work at runtime just like deserializing anything else with no guarantees about structure, like JSON or a Mongo DBObject. Also, Salat has utilities to leverage default args where supplied.
This is not possible, because it is impossible to verify at compile time that all parameters were passed in that map.