In Scala a Set is a function:
trait Set[A] extends (A => Boolean)
This make it impossible to have a covariant immutable Set because type A occurs in contravariant position. In contrast Seq is not defined as a function. There is already some content about the question why Sets and Seqs are designed this way:
Why is Scala's immutable Set not covariant in its type?
Scala: Why does Seq.contains take an Any argument, instead of an argument of the sequence type?
Why does Seq.contains accept type Any rather than the type parameter A?
One answer says that the reason for this is the mathematical background. But this answer wasn't explained a little more. So, what are the concrete advantages to define a Set as a function or what would be the disadvantages if it is implemented differently?
The set of type Set[A] has to have a method that tests if an element of type A is in the set. This method (apply) has to have a parameter of type A representing that element, and that parameter is in the contravariant position. This means that sets cannot be covariant in their type parameter A. So - it's not the extending of the function interface that makes it impossible to have covariant immutable sets, it's the existence of the contravariant apply method.
And for reasons of convenience, it makes sense to extend the Function1 interface to be able to pass sets around and treat them as functions.
By contrast, sequence abstraction doesn't have a method that tests if an element is in the sequence, it only has the indexing method - apply takes an integer index, and returns the element at that index. Sequences are also defined as functions, but functions of type Int => A (which are covariant in A), not A => Boolean, as sets.
If you want to know more about how type safety would be broken if sets were defined as covariant in their type parameter A, see this example in which the set implementation does some writing to private members for reasons of caching the lookups (below #uV is the annotation which disables variance checking and expensiveLookup is meant to simulate a call to a computationally expensive check if an element is in the set):
import annotation.unchecked.{uncheckedVariance => uV}
trait Set[+A] {
def apply(elem: A #uV): Boolean
}
class CachingSet[+A >: Null] extends Set[A] {
private var lastLookup: (A #uV, Boolean) = (null, false)
private def expensiveLookup(elem: A #uV) = (elem, true)
def apply(elem: A #uV): Boolean = {
if (elem != lastLookup._1) lastLookup = expensiveLookup(elem)
lastLookup._2
}
def lastQueriedElement: A = lastLookup._1
}
object Main extends App {
val css = new CachingSet[String]
val csa: CachingSet[AnyRef] = css
csa.apply(new AnyRef)
val s: String = css.lastQueriedElement // you'll get a ClassCastException here
}
In contrast Seq is not defined as a function.
Not true.
Seq[T] extends (Int) => T
Related
I am trying to understand how a case class can be passed as an argument to a function which accepts functions as arguments. Below is an example:
Consider the below function
def !![B](h: Out[B] => A): In[B] = { ... }
If I understood correctly, this is a polymorphic method which has a type parameter B and accepts a function h as a parameter. Out and In are other two classes defined previously.
This function is then being used as shown below:
case class Q(p: boolean)(val cont: Out[R])
case class R(p: Int)
def g(c: Out[Q]) = {
val rin = c !! Q(true)_
...
}
I am aware that currying is being used to avoid writing the type annotation and instead just writing _. However, I cannot grasp why and how the case class Q is transformed to a function (h) of type Out[B] => A.
EDIT 1 Updated !! above and the In and Out definitions:
abstract class In[+A] {
def future: Future[A]
def receive(implicit d: Duration): A = {
Await.result[A](future, d)
}
def ?[B](f: A => B)(implicit d: Duration): B = {
f(receive)
}
}
abstract class Out[-A]{
def promise[B <: A]: Promise[B]
def send(msg: A): Unit = promise.success(msg)
def !(msg: A) = send(msg)
def create[B](): (In[B], Out[B])
}
These code samples are taken from the following paper: http://drops.dagstuhl.de/opus/volltexte/2016/6115/
TLDR;
Using a case class with multiple parameter lists and partially applying it will yield a partially applied apply call + eta expansion will transform the method into a function value:
val res: Out[Q] => Q = Q.apply(true) _
Longer explanation
To understand the way this works in Scala, we have to understand some fundamentals behind case classes and the difference between methods and functions.
Case classes in Scala are a compact way of representing data. When you define a case class, you get a bunch of convenience methods which are created for you by the compiler, such as hashCode and equals.
In addition, the compiler also generates a method called apply, which allows you to create a case class instance without using the new keyword:
case class X(a: Int)
val x = X(1)
The compiler will expand this call to
val x = X.apply(1)
The same thing will happen with your case class, only that your case class has multiple argument lists:
case class Q(p: boolean)(val cont: Out[R])
val q: Q = Q(true)(new Out[Int] { })
Will get translated to
val q: Q = Q.apply(true)(new Out[Int] { })
On top of that, Scala has a way to transform methods, which are a non value type, into a function type which has the type of FunctionX, X being the arity of the function. In order to transform a method into a function value, we use a trick called eta expansion where we call a method with an underscore.
def foo(i: Int): Int = i
val f: Int => Int = foo _
This will transform the method foo into a function value of type Function1[Int, Int].
Now that we posses this knowledge, let's go back to your example:
val rin = c !! Q(true) _
If we just isolate Q here, this call gets translated into:
val rin = Q.apply(true) _
Since the apply method is curried with multiple argument lists, we'll get back a function that given a Out[Q], will create a Q:
val rin: Out[R] => Q = Q.apply(true) _
I cannot grasp why and how the case class Q is transformed to a function (h) of type Out[B] => A.
It isn't. In fact, the case class Q has absolutely nothing to do with this! This is all about the object Q, which is the companion module to the case class Q.
Every case class has an automatically generated companion module, which contains (among others) an apply method whose signature matches the primary constructor of the companion class, and which constructs an instance of the companion class.
I.e. when you write
case class Foo(bar: Baz)(quux: Corge)
You not only get the automatically defined case class convenience methods such as accessors for all the elements, toString, hashCode, copy, and equals, but you also get an automatically defined companion module that serves both as an extractor for pattern matching and as a factory for object construction:
object Foo {
def apply(bar: Baz)(quux: Corge) = new Foo(bar)(quux)
def unapply(that: Foo): Option[Baz] = ???
}
In Scala, apply is a method that allows you to create "function-like" objects: if foo is an object (and not a method), then foo(bar, baz) is translated to foo.apply(bar, baz).
The last piece of the puzzle is η-expansion, which lifts a method (which is not an object) into a function (which is an object and can thus be passed as an argument, stored in a variable, etc.) There are two forms of η-expansion: explicit η-expansion using the _ operator:
val printFunction = println _
And implicit η-expansion: in cases where Scala knows 100% that you mean a function but you give it the name of a method, Scala will perform η-expansion for you:
Seq(1, 2, 3) foreach println
And you already know about currying.
So, if we put it all together:
Q(true)_
First, we know that Q here cannot possibly be the class Q. How do we know that? Because Q here is used as a value, but classes are types, and like most programming languages, Scala has a strict separation between types and values. Therefore, Q must be a value. In particular, since we know class Q is a case class, object Q is the companion module for class Q.
Secondly, we know that for a value Q
Q(true)
is syntactic sugar for
Q.apply(true)
Thirdly, we know that for case classes, the companion module has an automatically generated apply method that matches the primary constructor, so we know that Q.apply has two parameter lists.
So, lastly, we have
Q.apply(true) _
which passes the first argument list to Q.apply and then lifts Q.apply into a function which accepts the second argument list.
Note that case classes with multiple parameter lists are unusual, since only the parameters in the first parameter list are considered elements of the case class, and only elements benefit from the "case class magic", i.e. only elements get accessors implemented automatically, only elements are used in the signature of the copy method, only elements are used in the automatically generated equals, hashCode, and toString() methods, and so on.
I have one abstract class with type parameter and few its implementations:
abstract class AbstractClass[T] {
def func: T
}
class DoubleClass extends AbstractClass[Double]{
def func = 0.0
}
and then I want to create a function that takes some sequence of such objects:
def someFunc(objs: Iterable[AbstractClass]) = objs.foreach(obj=>println(obj.func))
but it says "Class AbstractClass takes type parameters"
I am new at scala and definitely doing something wrong, but i can`t figure out what
It should in most cases be def someFunc[A](objs: Iterable[AbstractClass[A]]). In particular, this allows return type to depend on A, e.g.
def someFunc[A](objs: Iterable[AbstractClass[A]]) = objs.map(_.func)
returns Iterable[A].
Sometimes you may actually want to allow mixing AbstractClasses with different parameters. E.g. in your example you just print func, which can always be done. In this case, as Sascha Kolberg's answer says, use a wildcard:
def someFunc(objs: Iterable[AbstractClass[_]])
But if you find yourself using wildcards constantly, consider rethinking your design.
The simple solution would be to add the wildcard type as type argument to AbstractClass in your function:
def someFunc(objs: Iterable[AbstractClass[_]]) = objs.foreach(obj=>println(obj.func))
This way objs can be an iterable containing any kind of AbstractClass, so essentially a mixed type collection.
If you want to be sure, that the iterable argument of someFunc holds only instances of one implementation of AbstractClass[_], you can add another type parameter to someFunc:
def someFunc[A <: AbstractClass[_]](objs: Iterable[A]) = objs.foreach(obj=>println(obj.func))
<: is a type bound that basically says that A is a subclass of AbstractClass[_]
Going through Play Form source code right now and encountered this
def bindFromRequest()(implicit request: play.api.mvc.Request[_]): Form[T] = {
I am guessing it takes request as an implicit parameter (you don't have to call bindFromRequet(request)) of type play.api.mvc.Request[_] and return a generic T type wrapped in Form class. But what does [_] mean.
The notation Foo[_] is a short hand for an existential type:
Foo[A] forSome {type A}
So it differs from a normal type parameter by being existentially quantified. There has to be some type so your code type checks where as if you would use a type parameter for the method or trait it would have to type check for every type A.
For example this is fine:
val list = List("asd");
def doSomething() {
val l: List[_] = list
}
This would not typecheck:
def doSomething[A]() {
val l: List[A] = list
}
So existential types are useful in situations where you get some parameterized type from somewhere but you do not know and care about the parameter (or only about some bounds of it etc.)
In general, you should avoid existential types though, because they get complicated fast. A lot of instances (especially the uses known from Java (called wildcard types there)) can be avoided be using variance annotations when designing your class hierarchy.
The method doesn't take a play.api.mvc.Request, it takes a play.api.mvc.Request parameterized with another type. You could give the type parameter a name:
def bindFromRequest()(implicit request: play.api.mvc.Request[TypeParameter]): Form[T] = {
But since you're not referring to TypeParameter anywhere else it's conventional to use an underscore instead. I believe the underscore is special cased as a 'black hole' here, rather than being a regular name that you could refer to as _ elsewhere in the type signature.
I'm reflectively invoking a method whose argument might or might not be an instance of a value class. As the purpose of value classes is to avoid boxing of underlying value, if the parameter type is value class then the method in question will in fact expect unboxed value. To handle this case I'm trying to unwrap the underlying value from value class. I first need to determine if the argument is of a value class, and here I hit the first stumbling block:
def isObjectOfValueClass(arg: Any) =
classOf[AnyVal].isAssignableFrom(arg.getClass)
This doesn't work as expected, as the method returns true for:
case class NonValueClass(underlying: Int)
How can isObjectOfValueClass be implemented? Or is there a simpler way to reflectively invoke a method that might take object of a value class as an argument?
First, note that your isObjectOfValueClass will get a boxed version of your value class instances.
Second, it cannot work like you want. It's because classOf[AnyVal] == classOf[AnyRef] == <java.lang.Object>.
There's no runtime way to distinguish between a boxed value class and a reference class (Any doesn't have .instanceOf[T], AnyVal cannot be used in pattern matching or as parameter of .instanceOf[T], and what's most important, compiled value classes do not extend or implement AnyVal).
If you want it decided on compile time, then try:
case class IsAnyVal[-T](val value: Boolean) extends AnyVal
implicit def _noClueHowToNameThisImplicit_1 = IsAnyVal[AnyVal](true)
implicit def _noClueHowToNameThisImplicit_2 = IsAnyVal[AnyRef](false)
def isAnyVal[T](arg: T)(implicit ev: IsAnyVal[T]) = ev.value
scala> isAnyVal(1)
res4: Boolean = true
scala> isAnyVal("")
res5: Boolean = false
I'm not sure how you want to extract the sole field of the detected boxed value class instances without more accidental boxing. Besides, Hotspot is pretty good at optimizing small short-lived objects.
I know trait Foo[T] means T is a parametrized type.
But some times I can see trait Foo[T1,T2], or trait Foo[T1,T2,R], I cannot find anywhere describe the meaning of multiple types inside a type bracket, could you please point me the usages in this case? From what I speculate, Foo[T1,T2] just means, it defined two type parameters, it doesn't have to be take a T1 and return a T2.
When I read playframework documentation today, I again found myself confused about this question. In the documentation, it says:
A BodyParser[A] is basically an Iteratee[Array[Byte],A], meaning that
it receives chunks of bytes (as long as the web browser uploads some
data) and computes a value of type A as result.
This explanation sounds like, the second the type parameter inside a type bracket is a return type.
I also remember that trait Function2 [-T1, -T2, +R] extends AnyRef means a function that takes a T1 and T2, return a R.
Why do they put the return type in the bracket? Does it mean all the last parameter in a bracket is a return type? Or they just happened defined a new type R for the return type?
From what I speculate, Foo[T1,T2] just means, it defined two type parameters, it doesn't have to be take a T1 and return a T2.
A type parameter means nothing more than "I need any type but I'm not interested to know what it is for a concrete type", where 'I' is the programmer who writes the code. Type parameters can used like any other types such as Int, String or Complex - the only difference is that they are not known until one uses them.
See type Map[A, +B]. When you first read this, you can't know what the A and B are for, thus you have to read the documentation:
A map from keys of type A to values of type B.
It explains the types and their meaning. There is nothing more to know or understand. They are just two types. It is possible to call Map something like Map[Key, Value] but inside of source code it is better when type parameters have only one or two letters. This makes it easier to differ between the type parameters and concrete types.
It is the documentation which specifies what a type parameter means. And if there is no documentation you have to take a look to the sources and find their meaning by yourself. For example you have to do this with Function2 [-T1, -T2, +R]. The documentation tells us only this:
A function of 2 parameters.
Ok, we know that two of the three type parameters are parameters the function expects, but what is the third one? We take a look to the sources:
def apply(v1: T1, v2: T2): R
Ah, now we know that T1 and T2 are the parameters and that R is a return type.
Type parameters also can be found in method signatures like map:
class List[+A] {
..
def map[B](f: (A) ⇒ B): List[B]
}
This is how map looks like when you use it with a List. A can be any type - it is the type of the elements a list contains. B is another arbitrary type. When you know what map does then you know what B does. Otherwise you have to understand map before. map expects a function which can transform each element of a List to another element. Because you know that A stands for the elements of the List you can derive from yourself that B have to be the type A is transformed to.
To answer all your other questions: This shouldn't be done in a single answer. There are a lot of other questions and answers on StackOverflow which can also answer your questions.
Summary
When you see some type parameters for example in Foo[T1, T2] you should not start to cry. Think: "Ok, I have a Foo which expects a T1 and a T2 and if I want to know what they do I have to read documentation or the sources."
Multiple types inside a type bracket means type parametrization on multiple types. Take for example
trait Pair[A, B]
This is a pair of values one having type A the other having type B.
Update:
I think you are interpreting too much into the semantics of type parameters. A type parametrized by multiple parameters is just that and nothing more. The position of a specific type parameter in the list of type parameters does not make it special in any way. Specifically the last parameter in a list of type parameters does not need to stand for 'the return type'.
The sentence from the play framework which you quoted explains the semantics of the type parameters for this one specific type. It does not generalize to other types. The same holds for the Function types: here the last type parameter happens to mean 'the return type'. This is not necessarily the case for other types though. The type Pair[A, B] from above is such an example. Here B is the type of the second component of the pair. There is no notion of a 'return type' here at all.
Type parameters of a parametrized type can appear anywhere inside the definition of the parametrized type where a 'regular' type could appear. That is, type parameters are just names for types which are bound to the actual types only when the parametrized type itself is instantiated.
Consider the following definition of a class Tuple:
class Tuple[A, B](a: A, b: B)
It is instantiated to a type of a tuple of Int and String like this:
type TupleIntString = Tuple[Int, String]
Which is essentially the same as
class TupleIntString(a: Int, b: String)
For an official source check the Scala Language Specification. Specifically Section 3.4 "Base Types and Member Definitions" under 1. the 4th bullet point says: "The base types of a parameterized type C[T_1, ..., T_n] are the base types of type C , where every occurrence of a type parameter a_i of C has been replaced by the corresponding parameter type T_i."
I think your question can actually be broken in three separate problems:
What's with the multiple type parameters for classes/traits/etc. ?
A classic example is a map from one type of object to another. If you want the type for the keys to be different from type of the value, but keep both generic, you need two type parameters. So, a Map[A,B] takes keys of generic type A and maps to values of generic type B. A user that wants a map from Bookmarks to Pages would declare it as Map[Bookmark, Page]. Having only one type parameters would not allow this distinction.
From what I speculate, Foo[T1,T2] just means, it defined two type parameters, it doesn't have to be take a T1 and return a T2.
No, all type parameters are equal citizens, though they have a meaning in that direction for function objects. See below.
What are all those +/-'s ?
They limit what the type parameters can bind to. The Scala by Example tutorial has a good explanation. See Section 8.2 Variance Annotations.
What is a function in scala?
Why do they put the return type in the bracket? Does it mean all the
last parameter in a bracket is a return type? Or they just happened
defined a new type R for the return type?
The Scala by Example tutorial explains this well in Section 8.6 Functions.
Their role is a bit similar to the ones (i.e. multiple type parameter) in a class, since traits are, after all, classes (without any constructor) meant to be added to some other class as a mixin.
The Scala spec gives the following example for Trait with multiple parameters:
Consider an abstract class Table that implements maps from a type of keys A to a type of values B.
The class has a method set to enter a new key/value pair into the table, and a method get that returns an optional value matching a given key.
Finally, there is a method apply which is like get, except that it returns a given default value if the table is undefined for the given key. This class is implemented as follows.
abstract class Table[A, B](defaultValue: B) {
def get(key: A): Option[B]
def set(key: A, value: B)
def apply(key: A) = get(key) match {
case Some(value) => value
case None => defaultValue
}
}
Here is a concrete implementation of the Table class.
class ListTable[A, B](defaultValue: B) extends Table[A, B](defaultValue) {
private var elems: List[(A, B)]
def get(key: A) = elems.find(._1.==(key)).map(._2)
def set(key: A, value: B) = { elems = (key, value) :: elems }
}
Here is a trait that prevents concurrent access to the get and set operations of its
parent class
trait Synchronized Table[A, B] extends Table[A, B] {
abstract override def get(key: A): B =
synchronized { super.get(key) }
abstract override def set((key: A, value: B) =
synchronized { super.set(key, value) }
}
Note that SynchronizedTable does not pass an argument to its superclass, Table,
even though Table is defined with a formal parameter.
Note also that the super calls in SynchronizedTable’s get and set methods statically refer to abstract methods in class Table. This is legal, as long as the calling method is labeled abstract override (§5.2).
Finally, the following mixin composition creates a synchronized list table with
strings as keys and integers as values and with a default value 0:
object MyTable extends ListTable[String, Int](0) with SynchronizedTable
The object MyTable inherits its get and set method from SynchronizedTable.
The super calls in these methods are re-bound to refer to the corresponding implementations in ListTable, which is the actual supertype of SynchronizedTable in
MyTable.