This is my code:
val nums = (2 to 10).toList
val flags = List.tabulate(nums.size)(_ => 1)
val num_flags = mutable.AnyRefMap.fromZip(nums, flags)
It got the exception:
cmd6.sc:1: overloaded method value fromZip with alternatives:
[K <: AnyRef, V](keys: scala.collection.mutable.Iterable[K], values: scala.collection.mutable.Iterable[V])scala.collection.mutable.AnyRefMap[K,V] <and>
[K <: AnyRef, V](keys: Array[K], values: Array[V])scala.collection.mutable.AnyRefMap[K,V]
cannot be applied to (List[Int], List[Int])
val num_flags = mutable.AnyRefMap.fromZip(nums, flags)
^
Compilation Failed.
How to use the mutable.AnyRefMap.fromZip ? And why the exception?
If you look at the AnyRefMap.fromZip method declaration, you'll see the following constraint:
K <: AnyRef
This means that K has to be a subtype of AnyRef, where Int is a subtype of AnyVal. Thus, the compiler fails, telling you the constraints do not match.
I don't see a reason to use AnyRefMap here, if you want a mutable map, just use mutable.Map:
def main(args: Array[String]): Unit = {
val keys = (2 to 10).toList
val values = List.tabulate(nums.length)(_ => 1)
val numFlags = mutable.Map(keys.zip(values):_*)
}
Related
The following code works:
scala> import scala.language.implicitConversions
import scala.language.implicitConversions
scala> implicit val longToInt = (l: Long) => l.toInt
longToInt: Long => Int = $$Lambda$1821/0x000000010086e840#52bd9a27
scala> def printInt(n: Int) = println(n)
printInt: (n: Int)Unit
scala> val opt: Option[Long] = None
opt: Option[Long] = None
scala> val n = opt.getOrElse(0L)
n: Long = 0
scala> printInt(n)
0
However, the compiler throws a type mismatch error if we nest the getOrElse expression inside of the function call:
scala> printInt(opt.getOrElse(0L))
<console>:16: error: type mismatch;
found : AnyVal
required: Int
printInt(opt.getOrElse(0L))
^
Why does opt.getOrElse(0L) have type AnyVal?
Scala 2.12.8
When you write
printInt(opt.getOrElse(0L))
opt.getOrElse(0L) is typed with expected type Int. Option#getOrElse's signature is
getOrElse[B >: A](default: ⇒ B): B
Because it's generic, the compiler tries to find B such that opt.getOrElse[B](0L) has type Int. So B has to satisfy constraints B >: Long (because A in the above signature is Long) and B <: Int (from the return type). Obviously there's no such B. Scala specification says this must be an error, but doesn't say which, and here the compiler happens to report it after guessing B = AnyVal.
Another way to fix it is to specify the expected type for opt.getOrElse(0L):
printInt(opt.getOrElse(0L): Long)
Or the type parameter:
printInt(opt.getOrElse[Long](0L))
The signature of getOrElse is:
def getOrElse[B1 >: B](key: A, default: ⇒ B1): B1
printInt(opt.getOrElse(0L)) tells Scala that B1 ought to be Long, but Long is not a super-type of Int. The common supertype instead is AnyVal. Therefore you cannot make that assignment.
Try casting the result to a Long instead:
printInt(opt.getOrElse(0L).toLong)
I am trying to understand the mechanism with which scala implements default type converions from sub to super type in scala.Predef. From the literature I gathered that this is done with the function
implicit def conforms[A] = new A<:<A { def apply(a:A)=a }
The parameterless function conforms[A] returns the implicit conversion A=>B as its only
function value (as a callable of type A=>A and thus of type A=>B, whenver A<:B).
However when the compiler looks for an implicit type conversion it needs an implicit value
of type A=>B not a function returning such a value. Thus my question:
When looking for a default type conversion from A=>B, where A<:B, how does the compiler
get from the function conforms[A] to its unique value.
The implicit resolution seeks for subtypes too, A <: B => A => A <: A => B, as in List[Int] <: Seq[Int].
scala> :paste
// Entering paste mode (ctrl-D to finish)
implicit val x: List[Int] = List(1, 2, 3)
def f(implicit x: Seq[Int]): Int = x.head
f
// Exiting paste mode, now interpreting.
x: Seq[Int] = List(1, 2, 3)
f: (implicit x: Seq[Int])Int
res1: Int = 1
So when making type conversion we look for A => B with A <: B, and A => A fits.
I'm not sure if I understood you right, but the defs are followed while searching for value of the needed type. It doesn't matter whether function takes zero, one, or more parameters. For example with zero:
implicit def implicitList[A]: List[A] = List() //the only obvious case
scala> implicitly[Seq[Int]]
// res0: Seq[Int] = List()
Or two:
case class Foo(str: String)
case class Bar(str: String)
case class Quux(str: String)
implicit val foo = Foo("foo")
implicit val bar = Bar("bar")
// how to build quux:
implicit def quux(implicit foo: Foo, bar: Bar): Quux = Quux(foo.str + bar.str)
implicitly[Quux]
// res2: Quux = Quux(foobar)
If we add any of:
implicit def quux2(implicit quux: Quux): Quux = quux
implicit def quux3(implicit foo: Foo): Quux = Quux(foo.str)
implicit val quux4: Quux = Quux("quux")
implicit def quux5[A]: Quux = Quux("poly")
We make implicit resolution undecidable for Quux:
scala> implicitly[Quux]
<console>:29: error: ambiguous implicit values:
both method quux of type (implicit foo: Foo, implicit bar: Bar)Quux
and method quux2 of type (implicit quux: Quux)Quux
match expected type Quux
implicitly[Quux]
^
I.e. there could be only one def or val in scope returning the type we are interested. And that is easy to verify statically.
But they will work if any of those is the only one in scope.
While debugging my program, I found that I had made the mistake of supplying the wrong argument to the containsSlice method of a Seq[Char]. I had supplied a Seq[Boolean] which is of course never contained in the Seq[Char].
Why did the compiler let me do this? Can't this method be implemented in a type-safe way in the Scala collections library? I think it must have been done deliberately to be able to supply a Seq[Any], which could theoretically be all Chars. But shouldn't the designers have kept this method type-safe and add some non-type-safe method like containsAnySlice?
EDIT:
I've tried creating my own type-safe containsSlice method outside of the collection class hierarchy, but for some reason the code in the test method compiles while I had hoped it wouldn't:
object Seqs {
def containsSlice[A, B <: A](s1: Seq[A], s2: Seq[B]): Boolean = {
s1.containsSlice(s2)
}
def test = {
val sc: Seq[Char] = Seq('A','B','C')
val sb: Seq[Boolean] = Seq(true, false)
containsSlice(sc, sb)
}
}
I guess this is because the common supertype of Char and Boolean (AnyVal) is inferred for type parameter A, and I need to explicitly call containsSlice[Char](sc, sb) if I don't want that (but then I could just use sc.containsSlice[Char](sb)).
To make it not compile for incompatible Seqs, the only way I could do this is use 2 parameter lists so the correct type gets inferred:
object Seqs {
def containsSlice[A, B <: A](s1: Seq[A])(s2: Seq[B]): Boolean = {
s1.containsSlice(s2)
}
def test = {
val sc: Seq[Char] = Seq('A','B','C')
val sb: Seq[Boolean] = Seq(true, false)
containsSlice(sc)(sb) // does not compile, yay!
}
}
The problem is that Seq is declared to be covaraint in its type parameter: trait Seq[+A] this means that Seq[A] is a subclass of Seq[B] if A is a subclass of B. The parameter to containsSlice is naturally in a contra-variant position, which means that it CANNOT match the type parameter A, since A is already declared as covariant. Try writing this yourself:
trait MySeq[+A] {
def containsSlice(as: Seq[A]): Boolean
}
The compiler will complain:
error: covariant type A occurs in contravariant position in type Seq[A] of value as
def containsSlice(as: Seq[A]): Boolean
^
one error found
And you can if you play around with this, how you cannot guarantee type safety anyway. Lets pretend that the compiler allowed this definition. In your example you had a Seq[Char]. Well because of the covariance of Seq, this should be allowed:
val myseq: Seq[Char] = List('a','b','c')
val anyseq: Seq[Any] = myseq
We are allowed to do this because Seq[Char] is a subtype of Seq[Any] since Char is a subtype of Any. Now, what is the type of containsSlice on anyseq? its Seq[Any] since the type parameter of Seq in our anyseq is Any, and thus your type safety is gone.
containsSlice is just a call to indexOfSlice, which has the following signature:
indexOfSlice[B >: A](that: GenSeq[B]): Int
containsSlice could do the same thing.
It's useful to constrain the type param with a lower bound so you can do this:
apm#mara:~/tmp$ scalam -Ywarn-infer-any
Welcome to Scala version 2.11.0-M7 (OpenJDK 64-Bit Server VM, Java 1.7.0_25).
Type in expressions to have them evaluated.
Type :help for more information.
scala> "abcdef" contains 8
<console>:8: warning: a type was inferred to be `AnyVal`; this may indicate a programming error.
"abcdef" contains 8
^
res0: Boolean = false
The warning tells you that type safety has been compromised.
-Xlint includes -Ywarn-infer-any.
But check this out:
scala> "abcdef" indexOfSlice (1 to 10)
res1: Int = -1
No warning?
You can turn on the fancy new -Ytyper-debug to see:
| | | | | \-> [B >: Char](that: scala.collection.GenSeq[B], from: Int)Int <and> [B >: Char](that: scala.collection.GenSeq[B])Int
| | | | solving for (B: ?B)
and
| | | | solving for (B: ?B)
| | | | \-> Int
which seems to mean that in the presence of overloading, you don't get the warning.
That's because of how typechecking is done for overloading.
-Xprint:typer confirms that, of course, you wind up with AnyVal, but it must happen later:
private[this] val res0: Int = scala.this.Predef.augmentString("abcdef").indexOfSlice[AnyVal](scala.this.Predef.intWrapper(1).to(10));
We didn't really need another reason that overloading is evil, but did you know that println is also evil?
scala> println("abcdef" contains 8)
false
No warning.
It turns out that the warning is very conservative:
// Can warn about inferring Any/AnyVal as long as they don't appear
// explicitly anywhere amongst the formal, argument, result, or expected type.
Since println takes Any, that is our expected type for the expression, and we lose the warning.
In summary,
import reflect.runtime._
import universe._
case class Foo[+A](a: A) {
def f[B >: A : TypeTag](other: Foo[B]): String = typeTag[B].toString
def g[B] = "huh"
def j[B >: A : TypeTag](other: Foo[B]): String = typeTag[B].toString
def j[B >: A : TypeTag](other: Foo[B], dummy: Int): String = typeTag[B].toString
}
object Test extends App {
val x = Foo("abc") f Foo(3) // warn
val y = Foo("abc").g
val w = Foo("abc") j Foo(3) // nowarn
val z = Foo("abc") j (Foo(3), 0)
Console println s"$x $y $w $z"
val b = "abcdef" contains 8 // warn
println("abcdef" contains 8) // nowarn
implicit class Sectional[+A](val as: Seq[A]) {
def containsSection[B >: A](other: Seq[B]): Boolean = as containsSlice other
}
("abcdefg": Seq[Char]) containsSection (1 to 10) // warn
implicit class Sectional2(val as: String) {
def containsSection[B >: String](other: Seq[B]): Boolean = as containsSlice other
}
"abcdefg" containsSection (1 to 10) // warn
}
Too bad about special-casing String.
I would like to write a function that casts to type A, where A can be e.g. List[Int], or a more complicated parameterized type like Map[Int, List[Int]].
def castToType[A](x: Any): A = {
// throws if A is not the right type
x.asInstanceOf[A]
}
Right now, due to type erasure (I believe), the code merrily works even when the type is not correct. The error only manifests on access, witha ClassCastException.
val x = List(1, 2, 3)
val y = castToType[List[String]](x)
y(0) --> throws java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
Is there a way I can use manifests to make this work properly? Thanks!
Unfortunately, this in an inherent limitation of asInstanceOf. I'm actually surprised to see the scaladoc mention it in details:
Note that the success of a cast at runtime is modulo Scala's erasure semantics. Therefore the expression 1.asInstanceOf[String] will throw a ClassCastException at runtime, while the expression List(1).asInstanceOf[List[String]] will not. In the latter example, because the type argument is erased as part of compilation it is not possible to check whether the contents of the list are of the requested type.
If you're mainly concerned about failing fast on wrong cast for traversable which would likely be the main issue when getting stuff back from your DB/memcached interface, I was playing around forcing a cast of the head for traversable objects:
def failFastCast[A: Manifest, T[A] <: Traversable[A]](as: T[A], any: Any) = {
val res = any.asInstanceOf[T[A]]
if (res.isEmpty) res
else {
manifest[A].newArray(1).update(0, res.head) // force exception on wrong type
res
}
}
On a simple example it works:
scala> val x = List(1, 2, 3): Any
x: Any = List(1, 2, 3)
scala> failFastCast(List[String](), x)
java.lang.ArrayStoreException: java.lang.Integer
[...]
scala> failFastCast(List[Int](), x)
res22: List[Int] = List(1, 2, 3)
But not on a more complex one:
val x = Map(1 -> ("s" -> 1L)): Any
failFastCast(Map[Int, (String, String)](), x) // no throw
I wonder if there is a way to recursively drill down into A to keep casting until there is no more type parameters...
You are indeed correct - type erasure means that you cannot "cast" in such a way as to distinguish between List[Int] and List[String], for example. However, you can improve on the cast which you are performing, whereby A is erased in such a way as to mean that you cannot distinguish between an Int and a String:
def cast[A](a : Any) = a.asInstanceOf[A]
//... is erased to
def erasedCast(a : Any) = a.asInstanceOf[Any]
What you need are reified generics, using manifests
def cast[A <: AnyRef : Manifest](a : Any) : A
= manifest[A].erasure.cast(a).asInstanceOf[A]
Whilst the final cast is erased to AnyRef, at least you should have the correct Class[_] instance (manifest.erasure) to get the top level type correct. In action:
scala> cast[String]("Hey")
res0: String = Hey
scala> cast[java.lang.Integer]("Hey")
java.lang.ClassCastException
at java.lang.Class.cast(Class.java:2990)
at .cast(<console>:7)
at .<init>(<console>:9)
scala> cast[List[String]](List("Hey"))
res2: List[String] = List(Hey)
scala> cast[List[Int]](List("Hey"))
res3: List[Int] = List(Hey)
My advice is not to use nested reflection to decide whether the target was really a List[Int]: this is not generally feasible. For what should the following return?
cast[List[Int]](List[AnyVal](1, 2))
You could use shapeless's Typeable from Miles Sabin:
Type casting using type parameter
It handles erasure in many cases, though only specific ones:
scala> import shapeless._; import syntax.typeable._
import shapeless._
import syntax.typeable._
scala> val x = List(1, 2, 3)
x: List[Int] = List(1, 2, 3)
scala> val y = x.cast[List[String]]
y: Option[List[String]] = None
To see the set of cases that it handles you can refer to its source:
https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/typeable.scala
Yes, the problem occurs due to type erasure. If you try
val x = List(1,2,3)
val y = castToType[Int](x)
The exception is thrown right away, as expected. The same occurs when trying to cast to Array[String] or even Array[Int].
I don't think you can create a generic type converter that works will types inside collections and other objects. You will need to create a converter for each object type. For example:
def castToType[A](x: List[A]) = x.map(i => i.asInstanceOf[A])
Consider this solution:
trait -->[A, B] {
def ->(a: A): B
}
implicit val StringToInt = new -->[String, Int] {
def ->(a: String): Int = a.toInt
}
implicit val DateToLong = new -->[java.util.Date, Long] {
def ->(a: java.util.Date): Long = a.getTime
}
def cast[A,B](t:A)(implicit ev: A --> B):B= ev.->(t)
The advantage is that:
It is type safe - the compiler will tell you if the type cannot be casted
You can define casting rules by providing proper implicits
Now you can use it so:
scala> cast(new java.util.Date())
res9: Long = 1361195427192
scala> cast("123")
res10: Int = 123
EDIT
I've spent some time and wrote this advanced code. First let me show how to use it:
scala> "2012-01-24".as[java.util.Date]
res8: java.util.Date = Tue Jan 24 00:00:00 CET 2012
scala> "2012".as[Int]
res9: Int = 2012
scala> "2012.123".as[Double]
res12: Double = 2012.123
scala> "2012".as[Object] // this is not working, becouse I did not provide caster to Object
<console>:17: error: could not find implicit value for parameter $greater: -->[String,Object]
"2012".as[Object]
^
Pretty nice? See the scala magic:
trait -->[A, B] {
def ->(a: A): B
}
implicit val StringToInt = new -->[String, Int] {
def ->(a: String): Int = a.toInt
}
implicit val StringToDate = new -->[String, java.util.Date] {
def ->(a: String): java.util.Date = (new java.text.SimpleDateFormat("yyyy-MM-dd")).parse(a)
}
implicit val StringToDouble = new -->[String, Double] {
def ->(a: String): Double = a.toDouble
}
trait AsOps[A] {
def as[B](implicit > : A --> B): B
}
implicit def asOps[A](a: A) = new AsOps[A] {
def as[B](implicit > : A --> B) = > ->(a)
}
I have seen a function named implicitly used in Scala examples. What is it, and how is it used?
Example here:
scala> 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>:8: error: could not find implicit value for evidence parameter of type
Foo[Double]
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.
Also see How to investigate objects/types/etc. from Scala REPL? and Where does Scala look for implicits?
implicitly is avaliable in Scala 2.8 and is defined in Predef as:
def implicitly[T](implicit e: T): T = e
It is commonly used to check if an implicit value of type T is available and return it if such is the case.
Simple example from retronym's presentation:
scala> implicit val a = "test" // define an implicit value of type String
a: java.lang.String = test
scala> val b = implicitly[String] // search for an implicit value of type String and assign it to b
b: String = test
scala> val c = implicitly[Int] // search for an implicit value of type Int and assign it to c
<console>:6: error: could not find implicit value for parameter e: Int
val c = implicitly[Int]
^
Here are a few reasons to use the delightfully simple method implicitly.
To understand/troubleshoot Implicit Views
An Implicit View can be triggered when the prefix of a selection (consider for example, the.prefix.selection(args) does not contain a member selection that is applicable to args (even after trying to convert args with Implicit Views). In this case, the compiler looks for implicit members, locally defined in the current or enclosing scopes, inherited, or imported, that are either Functions from the type of that the.prefix to a type with selection defined, or equivalent implicit methods.
scala> 1.min(2) // Int doesn't have min defined, where did that come from?
res21: Int = 1
scala> implicitly[Int => { def min(i: Int): Any }]
res22: (Int) => AnyRef{def min(i: Int): Any} = <function1>
scala> res22(1) //
res23: AnyRef{def min(i: Int): Int} = 1
scala> .getClass
res24: java.lang.Class[_] = class scala.runtime.RichInt
Implicit Views can also be triggered when an expression does not conform to the Expected Type, as below:
scala> 1: scala.runtime.RichInt
res25: scala.runtime.RichInt = 1
Here the compiler looks for this function:
scala> implicitly[Int => scala.runtime.RichInt]
res26: (Int) => scala.runtime.RichInt = <function1>
Accessing an Implicit Parameter Introduced by a Context Bound
Implicit parameters are arguably a more important feature of Scala than Implicit Views. They support the type class pattern. The standard library uses this in a few places -- see scala.Ordering and how it is used in SeqLike#sorted. Implicit Parameters are also used to pass Array manifests, and CanBuildFrom instances.
Scala 2.8 allows a shorthand syntax for implicit parameters, called Context Bounds. Briefly, a method with a type parameter A that requires an implicit parameter of type M[A]:
def foo[A](implicit ma: M[A])
can be rewritten as:
def foo[A: M]
But what's the point of passing the implicit parameter but not naming it? How can this be useful when implementing the method foo?
Often, the implicit parameter need not be referred to directly, it will be tunneled through as an implicit argument to another method that is called. If it is needed, you can still retain the terse method signature with the Context Bound, and call implicitly to materialize the value:
def foo[A: M] = {
val ma = implicitly[M[A]]
}
Passing a subset of implicit parameters explicitly
Suppose you are calling a method that pretty prints a person, using a type class based approach:
trait Show[T] { def show(t: T): String }
object Show {
implicit def IntShow: Show[Int] = new Show[Int] { def show(i: Int) = i.toString }
implicit def StringShow: Show[String] = new Show[String] { def show(s: String) = s }
def ShoutyStringShow: Show[String] = new Show[String] { def show(s: String) = s.toUpperCase }
}
case class Person(name: String, age: Int)
object Person {
implicit def PersonShow(implicit si: Show[Int], ss: Show[String]): Show[Person] = new Show[Person] {
def show(p: Person) = "Person(name=" + ss.show(p.name) + ", age=" + si.show(p.age) + ")"
}
}
val p = Person("bob", 25)
implicitly[Show[Person]].show(p)
What if we want to change the way that the name is output? We can explicitly call PersonShow, explicitly pass an alternative Show[String], but we want the compiler to pass the Show[Int].
Person.PersonShow(si = implicitly, ss = Show.ShoutyStringShow).show(p)
Starting Scala 3 implicitly has been replaced with improved summon which has the advantage of being able to return a more precise type than asked for
The summon method corresponds to implicitly in Scala 2. It is
precisely the same as the the method in Shapeless. The difference
between summon (or the) and implicitly is that summon can return a
more precise type than the type that was asked for.
For example given the following type
trait F[In]:
type Out
def f(v: Int): Out
given F[Int] with
type Out = String
def f(v: Int): String = v.toString
implicitly method would summon a term with erased type member Out
scala> implicitly[F[Int]]
val res5: F[Int] = given_F_Int$#7d0e5fbb
scala> implicitly[res5.Out =:= String]
1 |implicitly[res5.Out =:= String]
| ^
| Cannot prove that res5.Out =:= String.
scala> val x: res5.Out = ""
1 |val x: res5.Out = ""
| ^^
| Found: ("" : String)
| Required: res5.Out
In order to recover the type member we would have to refer to it explicitly which defeats the purpose of having the type member instead of type parameter
scala> implicitly[F[Int] { type Out = String }]
val res6: F[Int]{Out = String} = given_F_Int$#7d0e5fbb
scala> implicitly[res6.Out =:= String]
val res7: res6.Out =:= String = generalized constraint
However summon defined as
def summon[T](using inline x: T): x.type = x
does not suffer from this problem
scala> summon[F[Int]]
val res8: given_F_Int.type = given_F_Int$#7d0e5fbb
scala> summon[res8.Out =:= String]
val res9: String =:= String = generalized constraint
scala> val x: res8.Out = ""
val x: res8.Out = ""
where we see type member type Out = String did not get erased even though we only asked for F[Int] and not F[Int] { type Out = String }. This can prove particularly relevant when chaining dependently typed functions:
The type summoned by implicitly has no Out type member. For this
reason, we should avoid implicitly when working with dependently typed
functions.
A "teach you to fish" answer is to use the alphabetic member index currently available in the Scaladoc nightlies. The letters (and the #, for non-alphabetic names) at the top of the package / class pane are links to the index for member names beginning with that letter (across all classes). If you choose I, e.g., you'll find the implicitly entry with one occurrence, in Predef, which you can visit from the link there.