What is "String with Int" supposed to mean? - scala

> val foo: PartialFunction[String, Unit] = { case i: String => }
foo: PartialFunction[String,Unit] = <function1>
> val bar: PartialFunction[Int, Unit] = { case i: Int => }
bar: PartialFunction[Int,Unit] = <function1>
> foo orElse bar
PartialFunction[String with Int,Unit] = <function1>
What is String with Int?. I don't think that's even possible.
> (foo orElse bar)(new String with Int)
error: illegal inheritance from final class String
(foo orElse bar)(new String with Int)
^
error: class Int needs to be a trait to be mixed in
(foo orElse bar)(new String with Int)
^
Shouldn't it be PartialFunction[Nothing,Unit]?

What is String with Int?
It's an intersection type. I.e. a value of this type must be an Int and a String simultaneously.
I don't think that's even possible.
Yes, this is an uninhabited type. However, in general if you replace Int and String with some types A and B, you'll get PartialFunction[A with B, Unit] and the compiler doesn't have a special case for this.

Well, as said before, it's a compound type, and it works for any two types (classes, traits), as in the following code:
class B
class C extends B
class D extends C
val bf: PartialFunction[B, Unit] = {case b: B => println("some b") }
val cf: PartialFunction[C, Unit] = {case c: C => println("some c") }
val g = bf orElse cf
g(new D) // some b
It's just that sometimes it lacks of sense in some contexts. These links may prove useful:
http://www.scala-lang.org/old/node/110
http://www.scala-lang.org/files/archive/spec/2.11/03-types.html#compound-types

Related

In Scala, fetched value of declared field cast to its class-declared type

I would like to ask how to achieve the following in Scala. Consider
scala> case class C(i:Int)
defined class C
scala> val c = C(1)
c: C = C(1)
Given a field of interest, in this case
scala> val fname = "i"
fname: String = i
we would like to retrieve the original value and type of field i in c.
A first, naive, attempt included the following,
scala> val f = c.getClass.getDeclaredField(fname)
f: java.lang.reflect.Field = private final int C.i
scala> f.setAccessible(true)
scala> f.getType
res3: Class[_] = int
However,
scala> val a:Int = f.get(c)
<console>:11: error: type mismatch;
found : Object
required: Int
val a:Int = f.get(c)
^
Put another way, how to fetch the Int value for i in c (*)
scala> :type -v case class C(i:Int)
// Type signature
AnyRef
with Product
with Serializable {
val i: Int <----------------------- (*)
private[this] val i: Int
def <init>(i: Int): C
def copy(i: Int): C
...
and for not necessarily Int type, consider field j in D,
scala> case class C(i:Int)
defined class C
scala> case class D(j:C)
defined class D
scala> :type -v case class D(j:C)
// Type signature
AnyRef
with Product
with Serializable {
val j: C
private[this] val j: C
def <init>(j: C): D
def copy(j: C): D
...
Thanks very much...
In Summary
Given
scala> f.get(c)
res1: Object = 1
and
scala> f.getType
res3: Class[_] = int
how to get
val a = 1
where a is of type Int, and knowing the type only from f.getType.
The static type of f.get(c) is Object, because it can be any class and any field. However, at the runtime it will return an Integer (the Java wrapper class for Int). You can cast it by using
f.get(c).asInstanceOf[Int]
or
f.getInt(c)
if you know in advance that you are calling for an Int field. If you don't, you can pattern match:
f.get(c) match {
case i: Integer => ...
case l: java.lang.Long => ...
case s: String => ...
// etc.
}
// actually compiles to same code, but avoids the need to use boxed classes
(f.get(c): Any) match {
case i: Int => ...
case l: Long => ...
case s: String => ...
// etc.
}
Note that the taken branch depends on the actual value of the field, not on its type; e.g. for val f: Any = "" the case s: String branch will be taken.
Or you can use f.getType to get its type and make your logic depend on that.

Implicit conversion with generic implicit parameter

I seems that combining implicit conversions with generic implicit parameters does not work, as in example 2b below:
object Test {
case class Foo(i: Int)
case class Bar(i: Int)
case class Zip(i: Int)
object Foo {
// 1)
implicit def toBar(foo: Foo)(implicit g: Int => Bar): Bar = g(foo.i)
// 2)
implicit def toT[T](foo: Foo)(implicit g: Int => T): T = g(foo.i)
}
// 1)
implicit val b = (i: Int) => Bar(i)
val bar: Bar = Foo(3)
// 2a)
implicit val z = (i: Int) => Zip(i)
val zip: Zip = Foo.toT(Foo(3))
// 2b)
val zip2: Zip = Foo(3) // <- compiler error, implicit conversion not applied
}
Is there any theoretical reason why this doesn't work, or is it a limitation of the implementation?
For what it's worth, if you run the following reduced version of your code
case class Foo(i: Int)
case class Zip(i: Int)
implicit def toT[T](foo: Foo)(implicit g: Int => T): T = g(foo.i)
implicit val z = (i: Int) => Zip(i)
val zip2: Zip = Foo(3) // <- compiler error, implicit conversion not applied
with -Yinfer-debug, you'll get lots of debug information (Scala 2.9.2) about what is going on behind the scenes. I am not familiar with Scala compiler internals, but the following two output snippets might hint at the problem. The first one is (line 51ff of the gist)
[inferImplicit view] pt = this.Foo => this.Zip
Implicit search in Context(Main.$anon.zip2#ValDef scope=1100551785) {
search this.Foo => this.Zip
target $anon.this.Foo.apply(3)
isView true
eligible toT: [T](foo: this.Foo)(implicit g: Int => T)T
}
and I interpret it as "we are looking for an implicit this.Foo => this.Zip and a candidate worth looking at is toT: [T](foo: this.Foo)(implicit g: Int => T)T.
This snippet is followed by output that suggests that Scala then tries to instantiate T, but line 81 finally says
inferMethodInstance, still undetermined: List(type T)
My interpretation is, that Scala somehow fails to instantiate T with Zip, which is why the candidate is finally discarded.
That said, I don't see a theoretical problem with your code, and I assume that it is only a shortcoming of the compiler.

How to read the class of a Scala object extending Any but not AnyRef?

I have an heterogeneous List like the following one:
val l = List(1, "One", true)
and I need to filter its objects by extracting only the ones belonging to a given Class. For this purpose I wrote a very simple method like this:
def filterByClass[A](l: List[_], c: Class[A]) =
l filter (_.asInstanceOf[AnyRef].getClass() == c)
Note that I am obliged to add the explicit conversion to AnyRef in order to avoid this compilation problem:
error: type mismatch;
found : _$1 where type _$1
required: ?{val getClass(): ?}
Note that implicit conversions are not applicable because they are ambiguous:
both method any2stringadd in object Predef of type (x: Any)scala.runtime.StringAdd
and method any2ArrowAssoc in object Predef of type [A](x: A)ArrowAssoc[A]
are possible conversion functions from _$1 to ?{val getClass(): ?}
l filter (_.getClass() == c)
However in this way the invocation of:
filterByClass(l, classOf[String])
returns as expected:
List(One)
but of course the same doesn't work, for example, with Int since they extends Any but not AnyRef, so by invoking:
filterByClass(l, classOf[Int])
the result is just the empty List.
Is there a way to make my filterByClass method working even with Int, Boolean and all the other classes extending Any?
The collect method already does what you want. For example to collect all Ints in a collection you could write
xs collect { case x: Int => x }
This of course only works when you hardcode the type but as primitives are handled differently from reference types it is actually better to do so. You can make your life easier with some type classes:
case class Collect[A](collect: PartialFunction[Any,A])
object Collect {
implicit val collectInt: Collect[Int] = Collect[Int]({case x: Int => x})
// repeat for other primitives
// for types that extend AnyRef
implicit def collectAnyRef[A <: AnyRef](implicit mf: ClassManifest[A]) =
Collect[A]({ case x if mf.erasure.isInstance(x) => x.asInstanceOf[A] })
}
def collectInstance[A : Collect](xs: List[_ >: A]) =
xs.collect(implicitly[Collect[A]].collect)
Then you can use it without even passing a Class[A] instance:
scala> collectInstance[Int](l)
res5: List[Int] = List(1)
scala> collectInstance[String](l)
res6: List[String] = List(One)
Using isInstanceOf:
scala> val l = List(1, "One", 2)
l: List[Any] = List(1, One, 2)
scala> l . filter(_.isInstanceOf[String])
res1: List[Any] = List(One)
scala> l . filter(_.isInstanceOf[Int])
res2: List[Any] = List(1, 2)
edit:
As the OP requested, here's another version that moves the check in a method. I Couldn't find a way to use isInstanceOf and so I changed the implementation to use a ClassManifest:
def filterByClass[A](l: List[_])(implicit mf: ClassManifest[A]) =
l.filter(mf.erasure.isInstance(_))
Some usage scenarios:
scala> filterByClass[String](l)
res5: List[Any] = List(One)
scala> filterByClass[java.lang.Integer](l)
res6: List[Any] = List(1, 2)
scala> filterByClass[Int](l)
res7: List[Any] = List()
As can be seen above, this solution doesn't work with Scala's Int type.
The class of an element in a List[Any] is never classOf[Int], so this is behaving as expected. Your assumptions apparently leave this unexpected, but it's hard to give you a better way because the right way is "don't do that."
What do you think can be said about the classes of the members of a heterogenous list? Maybe this is illustrative. I'm curious how you think java does it better.
scala> def f[T: Manifest](xs: List[T]) = println(manifest[T] + ", " + manifest[T].erasure)
f: [T](xs: List[T])(implicit evidence$1: Manifest[T])Unit
scala> f(List(1))
Int, int
scala> f(List(1, true))
AnyVal, class java.lang.Object
scala> f(List(1, "One", true))
Any, class java.lang.Object
This worked for me. Is this what you want?
scala> val l = List(1, "One", true)
l: List[Any] = List(1, One, true)
scala> l filter { case x: String => true; case _ => false }
res0: List[Any] = List(One)
scala> l filter { case x: Int => true; case _ => false }
res1: List[Any] = List(1)
scala> l filter { case x: Boolean => true; case _ => false }
res2: List[Any] = List(true)
Despite my solution could be less elegant than this one I find mine quicker and easier. I just defined a method like this:
private def normalizeClass(c: Class[_]): Class[_] =
if (classOf[AnyRef].isAssignableFrom((c))) c
else if (c == classOf[Int]) classOf[java.lang.Integer]
// Add all other primitive types
else classOf[java.lang.Boolean]
So by using it in my former filterByClass method as it follows:
def filterByClass[A](l: List[_], c: Class[A]) =
l filter (normalizeClass(c).isInstance(_))
the invocation of:
filterByClass(List(1, "One", false), classOf[Int])
just returns
List(1)
as expected.
At the end, this problem reduces to find a map between a primitive and the corresponding boxed type.
Maybe a help can arrive from scala.reflect.Invocation (not included in the final version of 2.8.0), the getAnyValClass function in particular (here slightly edited)
def getAnyValClass(x: Any): java.lang.Class[_] = x match {
case _: Byte => classOf[Byte]
case _: Short => classOf[Short]
case _: Int => classOf[Int]
case _: Long => classOf[Long]
case _: Float => classOf[Float]
case _: Double => classOf[Double]
case _: Char => classOf[Char]
case _: Boolean => classOf[Boolean]
case _: Unit => classOf[Unit]
case x#_ => x.asInstanceOf[AnyRef].getClass
}
With this function the filter is as easy as
def filterByClass[T: Manifest](l:List[Any]) = {
l filter (getAnyValClass(_) == manifest[T].erasure)
}
and the invocation is:
filterByClass[Int](List(1,"one",true))

Defining a Map from String to Function in Scala

I am trying to define a Map literal with key: String, value: (Any)=>String. I tried the following, but get a syntax error:
def foo(x: Int): String = /...
def bar(x: Boolean): String = /...
val m = Map[String, (Any) => String]("hello" -> foo, "goodbye" -> bar)
Funny that no one actually gave a type that would work. Here's one such:
def foo(x: Int): String = x.toString
def bar(x: Boolean): String = x.toString
val m = Map[String, (Nothing) => String]("hello" -> foo, "goodbye" -> bar)
The reason why it works this way is because Function1 is contra-variant on the input, so (Nothing) => String is a superclass of (Int) => String. It is also co-variant on the output, so (Nothing) => Any would be a superclass to any other Function1.
Of course, you can't use it like that. Without manifests, you can't even uncover what the original type of Function1 is. You could try something like this, though:
def f[T : Manifest](v: T) = v -> manifest[T]
val m = Map[String, ((Nothing) => String, Manifest[_])]("hello" -> f(foo), "goodbye" -> f(bar))
val IntManifest = manifest[Int]
val BooleanManifest = manifest[Boolean]
val StringManifest = manifest[String]
m("hello")._2.typeArguments match {
case List(IntManifest, StringManifest) =>
m("hello")._1.asInstanceOf[(Int) => String](5)
case List(BooleanManifest, StringManifest) =>
m("hello")._1.asInstanceOf[(Boolean) => String](true)
case _ => "Unknown function type"
}
Int => String is not a subclass of Any => String, rather, the contrary. You can't put (replace) an Int => String function when a code expects Any => String, since that code can apply the function with, say, "hi".
#Ben suggestion works, but how is it useful? you can't invoke the function once you get it from the Map.
If you really want to do this, maybe define foo as a partial function:
val foo: PartialFunction[Any, String] = {case i: Int => ....}
Obviously, this will fail at runtime if you pass it a string, but you can always test if the function is ok for use with your parameter by using isDefinedAt. (another alternative may be manifests, but I don't see the value here)
If I let the compiler infer it I seem to get an illegal type:
scala> val m = Map("hello" -> foo _, "goodbye" -> bar _)
m: scala.collection.immutable.Map[java.lang.String,(Boolean with Int) => String] =
Map((hello,<function1>), (goodbye,<function1>))
scala> m("hello")(8)
<console>:9: error: type mismatch;
found : Int(8)
required: Boolean with Int
m("hello")(8)
scala> var q = new Boolean with Int
<console>:5: error: illegal inheritance from final class Boolean
var q = new Boolean with Int
Anyway, what you want is not the type Any but a generic of "any type" which is _:
scala> val mm = Map[String, (_) => String]("hello" -> foo _, "goodbye" -> bar _)
mm: scala.collection.immutable.Map[String,Function1[_, String]] =
Map((hello,<function1>), (goodbye,<function1>))
I just posted a question about how to invoke such functions because I don't actually know.
Trait Function1 is contravariant for parameter, so def foo(x: Int): String is not a (Any) => String. So the following would work:
scala> def baz(x: Any): String = "baz"
baz: (x: Any)String
scala> val m2 = Map[String, (String) => String]("hello" -> baz)
m2: scala.collection.immutable.Map[String,(String) => String] = Map((hello,<function1>))
This is how I did it to fulfill a similar requirement.
object MapToMethods {
private def increment(x: Int): Int = x+1
private def decrement(x: Int): Int = x-1
val m: Map[String, Int => Int] =Map("increment" -> increment, "decrement" ->decrement)
println(m("increment")(2)) //prints 3
println(m("decrement")(3)) //prints 2
}

scala tuple unpacking

I know this question has come up many times in different ways. But it is still not clear to me. Is there a way to achieve the following.
def foo(a:Int, b:Int) = {}
foo(a,b) //right way to invoke foo
foo(getParams) // is there a way to get this working without explicitly unpacking the tuple??
def getParams = {
//Some calculations
(a,b) //where a & b are Int
}
It's a two step procedure. First turn foo into a function, then call tupled on it to make it a function of a tuple.
(foo _).tupled(getParams)
#dave-griffith is dead on.
You can also call:
Function.tupled(foo _)
If you want to wander into "way more information than I asked for" territory, there are also methods built into partially applied functions (and on Function) for currying. A few input/output examples:
scala> def foo(x: Int, y: Double) = x * y
foo: (x: Int,y: Double)Double
scala> foo _
res0: (Int, Double) => Double = <function2>
scala> foo _ tupled
res1: ((Int, Double)) => Double = <function1>
scala> foo _ curried
res2: (Int) => (Double) => Double = <function1>
scala> Function.tupled(foo _)
res3: ((Int, Double)) => Double = <function1>
// Function.curried is deprecated
scala> Function.curried(foo _)
warning: there were deprecation warnings; re-run with -deprecation for details
res6: (Int) => (Double) => Double = <function1>
Wherein the curried version is invoked with multiple argument lists:
scala> val c = foo _ curried
c: (Int) => (Double) => Double = <function1>
scala> c(5)
res13: (Double) => Double = <function1>
scala> c(5)(10)
res14: Double = 50.0
Finally, you can also uncurry/untuple if needed. Function has builtins for this:
scala> val f = foo _ tupled
f: ((Int, Double)) => Double = <function1>
scala> val c = foo _ curried
c: (Int) => (Double) => Double = <function1>
scala> Function.uncurried(c)
res9: (Int, Double) => Double = <function2>
scala> Function.untupled(f)
res12: (Int, Double) => Double = <function2>
Function.tupled(foo _)(getParams) or the one suggested by Dave.
EDIT:
To respond to your comment:
What if foo happens to be the
constructor of some class?
In that case, this trick won't work.
You can write a factory method in the companion object of your class and then obtain the tupled version of its apply method using one of the aforementioned techniques.
scala> class Person(firstName: String, lastName: String) {
| override def toString = firstName + " " + lastName
| }
defined class Person
scala> object Person {
| def apply(firstName: String, lastName: String) = new Person(firstName, lastName)
| }
defined module Person
scala> (Person.apply _).tupled(("Rahul", "G"))
res17: Person = Rahul G
With case classes you get a companion object with an apply method for free, and thus this technique is more convenient to use with case classes.
scala> case class Person(firstName: String, lastName: String)
defined class Person
scala> Person.tupled(("Rahul", "G"))
res18: Person = Person(Rahul,G)
I know that's a lot of code duplication but alas... we don't have macros (yet)! ;)
I appreciate some of the other answers which were closer to what you asked for, but I found it easier for a current project to add another function which converts tuple parameters into the split parameters:
def originalFunc(a: A, b: B): C = ...
def wrapperFunc(ab: (A, B)): C = (originalFunc _).tupled(ab)
Now, you can implement foo and make it take a param of the Tuple2 class like so.
def foo(t: Tuple2[Int, Int]) = {
println("Hello " + t._1 + t._2)
"Makes no sense but ok!"
}
def getParams = {
//Some calculations
val a = 1;
val b = 2;
(a, b) //where a & b are Int
}
// So you can do this!
foo(getParams)
// With that said, you can also do this!
foo(1, 3)