I'm new to Scala and I'm using the shapeless library to manipulate tuples. (Though this isn't specific to shapeless)
I've run in to a problem related to implicit parameters, which I don't quite understand. Here are there signatures:
def reverse(implicit reverse: Reverse[T]): reverse.Out = reverse(t)
def drop[N <: Nat](implicit drop: Drop[T, N]): drop.Out = drop(t)
And here is it in use:
val foo = ("foo","bar","other").reverse
val bar = ("foo","bar","other").drop(1)
However on Scala 2.10 I get this error:
Error:(25, 37) could not find implicit value for parameter reverse:
shapeless.ops.tuple.Reverse[(String, String, String)]
val zzy = ("foo","bar","other").reverse
Error:(29, 37) not enough arguments for method reverse: (implicit
reverse: shapeless.ops.tuple.Reverse[(String, String,
String)])reverse.Out. Unspecified value parameter reverse.
val foo = ("foo","bar","other").reverse
^
I'm not sure what the implicit parameter is that it is trying to reference, or why I need it. Also, this seems to work on 2.11 (but IntelliJ flags it)
On Scala 2.10.x you need to have the macro-paradise plugin included in your build: see the shapeless documentation here.
IntelliJ often reports spurious errors against code which uses aspects of the Scala type system which it doesn't have adequate support for. This is especially true of code which uses dependent method types as reverse and drop above do (notice that the result type of the methods depend on the argument values). In all cases the command line compiler is authoritative.
Related
I have a List[Any] which I want to convert to a JsArray.
List with type works:
Json.arr(List("1"))
But:
Json.arr(List("1").asInstanceOf[List[Any]])
throws:
diverging implicit expansion for type play.api.libs.json.Reads[T1]
starting with method oFormatFromReadsAndOWrites in object OFormat
How can I convert List[Any] to JsArray?
I tried:
implicit val listAnyFormat: OFormat[List[Any]] = Json.format[List[Any]]
But I get thrown with:
No instance of Reads is available for scala.collection.immutable.Nil in the implicit scope
Using Play 2.8.x and Scala 2.11.8
You can't.
At least not without defining a Format[Any] which can be done technically but will likely not cover all the possible cases.
The question is why do you have a List[Any] in the first place? It has not much sense in Scala world.
It would be better if you could have a List[Something] where Something has a known set of subtypes and each of them has a Format.
Trying to understand akka marshalling/unmarshalling and found a lot of scala implicit magic that goes on in the background and under the hood.
Question:
Is there a way to find which implicit constructs are effective during an execution.
Things that would be useful to know:
- what implicit declarations and conversions are effective
- where they are declared
What I'm thinking is an IDE plugin for this may be? To be used during code debug?
I think this would help in understanding akka marshalling/unmarshalling but also it would be useful generally wherever complex implicit features are used.
Implicits are selected at compile time.
With -Xlog-implicit-conversions:
scala 2.13.0-M5> "42".toInt
^
applied implicit conversion from String("42") to ?{def toInt: ?} = implicit def augmentString(x: String): scala.collection.StringOps
res0: Int = 42
scala 2.13.0-M5> "42".toInt //print<TAB>
scala.Predef.augmentString("42").toInt // : Int
-Xlog-implicits explains when implicits do not apply.
IntelliJ has "show implicits".
Compiling a program that contains a type evidence parameter in Scala (such as T <:< U) can cause a warning when -Ywarn-unused is passed to the compiler. Especially in the case when the type evidence parameter is used to verify a constraint encoded using phantom types, this warning is likely to occur.
As an example, compiling the file here:
https://github.com/hseeberger/demo-phantom-types/blob/master/src/main/scala/de/heikoseeberger/demophantomtypes/Hacker.scala returns the following:
# scalac -Ywarn-unused Hacker.scala
Hacker.scala:42: warning: parameter value ev in method hackOn is never used
def hackOn(implicit ev: IsCaffeinated[S]): Hacker[State.Decaffeinated] = {
^
Hacker.scala:47: warning: parameter value ev in method drinkCoffee is never used
def drinkCoffee(implicit ev: IsDecaffeinated[S]): Hacker[State.Caffeinated] = {
^
two warnings found
It's clear to me that the parameter ev is not actually necessary at runtime, but the parameter is useful at compile time. Is there any way to instruct the compiler to ignore this case, while still raising the warning for unused function parameters in other contexts?
For example, I think instructing the compiler to ignore implicit parameters of class <:< or =:= would solve this issue, but I'm not sure how that could be accomplished.
I often find myself adding this because of either -Ywarn-unused or -Ywarn-value-discard:
package myproject
package object syntax {
implicit class IdOps[A](a: A) {
def unused: Unit = ()
}
}
Lets you do ev.unused in the code to explicitly "specify" that the value is not going to be used or is only there for side effects. You're not using class field in the definition, but that's okay for -Ywarn-unused.
Your other option is to use silencer plugin to suppress warnings for these few methods.
Many years later, it's worth to mention there is am #unused annotation available (since when, I am not sure):
import scala.annotation.unused
def drinkCoffee(implicit #unused ev: IsDecaffeinated[S]): Hacker[State.Caffeinated]
Consequently, you can not use a context-bounds
In Scala REPL I can use Seq[String]() as a default value for a parameter of type Seq[T].
Welcome to Scala version 2.11.7 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_101).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def d[T](foo: Seq[T] = Seq[String]()) = 12
d: [T](foo: Seq[T])Int
scala> d()
res0: Int = 12
Trying the same in IDEA, it complains “Seq[String] doesn't conform to expected type Seq[T]”. Why?
IntelliJ IDEA 2016.2.4
Scala Plugin 2016.2.1
Scala 2.11.7
Note 1: Sorry, I know that my example function does not make much sense. However, my real (and useful) function is unnecessarily complex to post it here.
Note 2: At first, instead of type T my type name in the example was Any which was not a good idea (because it shadowed scala.Any) and caused some confusion. Thus I fixed that.
When you say def d[Any], the Any here is a generic place holder. It does not point to class Any in scala. It basically shadows the Any class defined globally in scala. So, when you assign Seq[String] to Seq[Any], the compiler does not know any relation between String and Any. Note that Any could be replaced with any character / word as generic place holder. The result would be the same.
Now coming, to why this works in REPL, I am not exactly sure why REPL accepts if Seq[String] when given as a default value, but I was able to reproduce the error in repl when I do the same operation inside the method body.
The following code in REPL throws error:
def d[Any](foo: Seq[Any]) = {
val a: Seq[Any] = Seq[String]()
}
<console>:12: error: type mismatch;
found : Seq[String]
required: Seq[Any]
val a: Seq[Any] = Seq[String]()
^
I am not sure why REPL was not able to catch the error while given as a default argument.
One alternative theory is, in general when you use generics, the value of the type will be determined based on the caller. For example,
def d[A](a:A) = {}
d(1) // Type of A is Int
d("a") // Type of A is String
So, when you give default value, it assigns the value of String to Any. hence the compilation success.Intellij's Type Checker works based on the first theory and shows an error. But strangely as someone pointed out earlier, the compilation succeeds.
Since Scala 2.7.2 there is something called Manifest which is a workaround for Java's type erasure. But how does Manifest work exactly and why / when do you need to use it?
The blog post Manifests: Reified Types by Jorge Ortiz explains some of it, but it doesn't explain how to use it together with context bounds.
Also, what is ClassManifest, what's the difference with Manifest?
I have some code (part of a larger program, can't easily include it here) that has some warnings with regard to type erasure; I suspect I can solve these by using manifests, but I'm not sure exactly how.
The compiler knows more information about types than the JVM runtime can easily represent. A Manifest is a way for the compiler to send an inter-dimensional message to the code at runtime about the type information that was lost.
It isn't clear if a Manifest would benefit the errors you are seeing without knowing more detail.
One common use of Manifests is to have your code behave differently based on the static type of a collection. For example, what if you wanted to treat a List[String] differently from other types of a List:
def foo[T](x: List[T])(implicit m: Manifest[T]) = {
if (m <:< manifest[String])
println("Hey, this list is full of strings")
else
println("Non-stringy list")
}
foo(List("one", "two")) // Hey, this list is full of strings
foo(List(1, 2)) // Non-stringy list
foo(List("one", 2)) // Non-stringy list
A reflection-based solution to this would probably involve inspecting each element of the list.
A context bound seems most suited to using type-classes in scala, and is well explained here by Debasish Ghosh:
http://debasishg.blogspot.com/2010/06/scala-implicits-type-classes-here-i.html
Context bounds can also just make the method signatures more readable. For example, the above function could be re-written using context bounds like so:
def foo[T: Manifest](x: List[T]) = {
if (manifest[T] <:< manifest[String])
println("Hey, this list is full of strings")
else
println("Non-stringy list")
}
A Manifest was intended to reify generic types that get type-erased to run on the JVM (which does not support generics). However, they had some serious issues: they were too simplistic, and were unable to fully support Scala's type system. They were thus deprecated in Scala 2.10, and are replaced with TypeTags (which are essentially what the Scala compiler itself uses to represent types, and therefore fully support Scala types). For more details on the difference, see:
Scala: What is a TypeTag and how do I use it?
How do the new Scala TypeTags improve the (deprecated) Manifests?
In other words
when do you need it?
Before 2013-01-04, when Scala 2.10 was released.
Not a complete answer, but regarding the difference between Manifest and ClassManifest, you can find an example in the Scala 2.8 Array paper:
The only remaining question is how to implement generic array creation. Unlike Java, Scala allows an instance creation new Array[T] where T is a type parameter. How can this be implemented, given the fact that there does not exist a uniform array representation in Java?
The only way to do this is to require additional runtime information which describes the type T. Scala 2.8 has a new mechanism for this, which is called a Manifest. An object of type Manifest[T] provides complete information about the type T.
Manifest values are typically passed in implicit parameters; and the compiler knows how to construct them for statically known types T.
There exists also a weaker form named ClassManifest which can be constructed from knowing just the top-level class of a type, without necessarily knowing all its argument types.
It is this type of runtime information that’s required for array creation.
Example:
One needs to provide this information by passing a ClassManifest[T] into the
method as an implicit parameter:
def tabulate[T](len:Int, f:Int=>T)(implicit m:ClassManifest[T]) = {
val xs = new Array[T](len)
for (i <- 0 until len) xs(i) = f(i)
xs
}
As a shorthand form, a context bound1 can be used on the type parameter T instead,
(See this SO question for illustration)
, giving:
def tabulate[T: ClassManifest](len:Int, f:Int=>T) = {
val xs = new Array[T](len)
for (i <- 0 until len) xs(i) = f(i)
xs
}
When calling tabulate on a type such as Int, or String, or List[T], the Scala compiler can create a class manifest to pass as implicit argument to tabulate.
Let's also chck out manifest in scala sources (Manifest.scala), we see:
Manifest.scala:
def manifest[T](implicit m: Manifest[T]) = m
So with regards to following example code:
def foo[A](somelist: List[A])(implicit m: Manifest[A]): String = {
if (m <:< manifest[String]) {
"its a string"
} else {
"its not a string"
}
}
we can see that the manifest function searches for an implicit m: Manifest[T] which satisfies the type parameter you provide in our example code it was manifest[String]. So when you call something like:
if (m <:< manifest[String]) {
you are checking if the current implicit m which you defined in your function is of type manifest[String] and as the manifest is a function of type manifest[T] it would search for a specific manifest[String] and it would find if there is such an implicit.