Could some one please explain the generics involved in the following code from play framework
class AuthenticatedRequest[A, U](val user: U, request: Request[A]) extends WrappedRequest[A](request)
class AuthenticatedBuilder[U](userinfo: RequestHeader => Option[U],
onUnauthorized: RequestHeader => Result = _ => Unauthorized(views.html.defaultpages.unauthorized()))
extends ActionBuilder[({ type R[A] = AuthenticatedRequest[A, U] })#R]
The ActionBuilder actualy has type R[A], it is getting reassigned, this much I understand. please explain the intricacies of the syntax
The bit that's confusing you is called a "type lambda". If you search for "scala type lambda", you'll find lots of descriptions and explanations. See e.g. here, from which I'm drawing a lot of inspiration. (Thank you Bartosz Witkowski!)
To describe it very simply, you can think of it as a way to provide a default argument to a type constructor. I know, huh?
Let's break that down. If we have...
trait Unwrapper[A,W[_]] {
/* should throw an Exception if we cannot unwrap */
def unwrap( wrapped : W[A] ) : A
}
You could define an OptionUnwrapper easily enough:
class OptionUnwrapper[A] extends Unwrapper[A,Option] {
def unwrap( wrapped : Option[A] ) : A = wrapped.get
}
But what if we want to define an unwrapper for the very similar Either class, which takes two type parameters [A,B]. Either, like Option, is often used as a return value for things that might fail, but where you might want to retain information about the failure. By convention, "success" results in a Right object containing a B, while failure yields a Left object containing an A. Let's make an EitherUnwrapper, so we have an interface in common with Option to unwrap these sorts of failable results. (Potentially even useful!)
class EitherUnwrapper[A,B] extends Unwrapper[B,Either] { // unwrap to a successful result of type B
def unwrap( wrapped : Either[A,B] ) : B = wrapped match {
case Right( b ) => b // we ignore the left case, allowing a MatchError
}
}
This is conceptually fine, but it doesn't compile! Why not? Because the second parameter of Unwrapper was W[_], that is a type that accepts just one parameter. How can we "adapt" Either's type constructor to be a one parameter type? If we needed a version of an ordinary function or constructor with fewer arguments, we might supply default arguments. So that's exactly what we'll do.
class EitherUnwrapper[A,B] extends Unwrapper[B,({type L[C] = Either[A,C]})#L] {
def unwrap( wrapped : Either[A,B] ) : B = wrapped match {
case Right( b ) => b
}
}
The type alias part
type L[C] = Either[A,C]
adapts Either into a type that requires just one type parameter rather than two, by supplying A as a default first type parameter. But unfortunately, scala doesn't allow you to define type aliases just anywhere: they have to live in a class, trait, or object. But if you define the trait in an enclosing scope, you might not have access to the default value you need for type A! So, the trick is to define a throwaway inner class in a place where A is defined, just where you need the new type.
A set of curly braces can (depending on context) be interpreted as a type definition in scala, for a structural type. For instance in...
def destroy( rsrc : { def close() } ) = rsrc.close()
...the curly brace defines a structural type meaning any object with a close() function. Structural types can also include type aliases.
So { type L[C] = Either[A,C] } is just the type of any object that contains the type alias L[C]. To extract an inner type from an enclosing type -- rather than an enclosing instance -- in Scala, we have to use a type projection rather than a dot. The syntax for a type projection is EnclosingType#InnerType. So, we have { type L[C] = Either[A,C] }#L. For reasons that elude me, the Scala compiler gets confused by that, but if we put the type definition in parentheses, everything works, so we have ({ type L[C] = Either[A,C] })#L.
Which is pretty precisely analogous to ({ type R[A] = AuthenticatedRequest[A, U] })#R in your question. ActionBuilder needs to be parameterized with a type that takes one parameter. AuthenticatedRequest takes two parameters. To adapt AuthenticatedRequest into a type suitable for ActionBuilder, U is provided as a default parameter in the type lambda.
Related
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 have the following code:
sealed trait A
case class B[T](v: T) extends A
case class C[T](v: T) extends A
object Test {
def swap(a: A): A = a match {
case a: B[t] => C[t](a.v) // works!
case C[t](v) => B[t](v) // error: C[t] does not take parameters
}
}
I would expect either both cases to fail or both of them to work. What's the meaning of the error for the second case? Is there a syntax destructuring parametric case-classes?
Note: Here, 't' in lower case is essential. If it were 'T', the checker would be looking for it in the type parameters of the method.
When you do a match { case C(v) => ??? }, you actually call unapply method of the C companion object, something like this: C.unapply(a) match {Some(v) => ???}
There is only one C object, not an entire family of C[t]. There is no object you can refer to as C[Int], so case C[t](v) => doesn't make sense.
In your example, you use B[t] as a type, not as a pattern, and that's why it works. Note that while the match may succeed, you won't get anything in t, because of type erasure.
When you call C[t](a.v), then first of all, compiler erases type t anyway, and second, this is rewritten to a call to apply method on the companion object: C.apply[t](a.v). Note that the type parameter is on the method call, not on the object.
Simply put, it is not part of the language.
When used in this position, the compiler is looking for the type in the environment, as if it were a usual uppercase type. The type capturing that you are trying to do seems to only work in the case x:Y[z] => ... form of a case statement.
Type capturing in this fashion is not a well know part of the language and had me running to the Scala reference document for the details (Section 8.3). I personally find the that the distinction between upper and lowercase here not to my liking.
In your example t takes on the type of Any as the type information for the parameter is not available from A.
I'm seeing something I do not understand. I have a hierarchy of (say) Vehicles, a corresponding hierarchy of VehicalReaders, and a VehicleReader object with apply methods:
abstract class VehicleReader[T <: Vehicle] {
...
object VehicleReader {
def apply[T <: Vehicle](vehicleId: Int): VehicleReader[T] = apply(vehicleType(vehicleId))
def apply[T <: Vehicle](vehicleType VehicleType): VehicleReader[T] = vehicleType match {
case VehicleType.Car => new CarReader().asInstanceOf[VehicleReader[T]]
...
Note that when you have more than one apply method, you must specify the return type. I have no issues when there is no need to specify the return type.
The cast (.asInstanceOf[VehicleReader[T]]) is the reason for the question - without it the result is compile errors like:
type mismatch;
found : CarReader
required: VehicleReader[T]
case VehicleType.Car => new CarReader()
^
Related questions:
Why cannot the compiler see a CarReader as a VehicleReader[T]?
What is the proper type parameter and return type to use in this situation?
I suspect the root cause here is that VehicleReader is invariant on its type parameter, but making it covariant does not change the result.
I feel like this should be rather simple (i.e., this is easy to accomplish in Java with wildcards).
The problem has a very simple cause and really doesn't have anything to do with variance. Consider even more simple example:
object Example {
def gimmeAListOf[T]: List[T] = List[Int](10)
}
This snippet captures the main idea of your code. But it is incorrect:
val list = Example.gimmeAListOf[String]
What will be the type of list? We asked gimmeAListOf method specifically for List[String], however, it always returns List[Int](10). Clearly, this is an error.
So, to put it in words, when the method has a signature like method[T]: Example[T] it really declares: "for any type T you give me I will return an instance of Example[T]". Such types are sometimes called 'universally quantified', or simply 'universal'.
However, this is not your case: your function returns specific instances of VehicleReader[T] depending on the value of its parameter, e.g. CarReader (which, I presume, extends VehicleReader[Car]). Suppose I wrote something like:
class House extends Vehicle
val reader = VehicleReader[House](VehicleType.Car)
val house: House = reader.read() // Assuming there is a method VehicleReader[T].read(): T
The compiler will happily compile this, but I will get ClassCastException when this code is executed.
There are two possible fixes for this situation available. First, you can use existential (or existentially quantified) type, which can be though as a more powerful version of Java wildcards:
def apply(vehicleType: VehicleType): VehicleReader[_] = ...
Signature for this function basically reads "you give me a VehicleType and I return to you an instance of VehicleReader for some type". You will have an object of type VehicleReader[_]; you cannot say anything about type of its parameter except that this type exists, that's why such types are called existential.
def apply(vehicleType: VehicleType): VehicleReader[T] forSome {type T} = ...
This is an equivalent definition and it is probably more clear from it why these types have such properties - T type is hidden inside parameter, so you don't know anything about it but that it does exist.
But due to this property of existentials you cannot really obtain any information about real type parameters. You cannot get, say, VehicleReader[Car] out of VehicleReader[_] except via direct cast with asInstanceOf, which is dangerous, unless you store a TypeTag/ClassTag for type parameter in VehicleReader and check it before the cast. This is sometimes (in fact, most of time) unwieldy.
That's where the second option comes to the rescue. There is a clear correspondence between VehicleType and VehicleReader[T] in your code, i.e. when you have specific instance of VehicleType you definitely know concrete T in VehicleReader[T] signature:
VehicleType.Car -> CarReader (<: VehicleReader[Car])
VehicleType.Truck -> TruckReader (<: VehicleReader[Truck])
and so on.
Because of this it makes sense to add type parameter to VehicleType. In this case your method will look like
def apply[T <: Vehicle](vehicleType: VehicleType[T]): VehicleReader[T] = ...
Now input type and output type are directly connected, and the user of this method will be forced to provide a correct instance of VehicleType[T] for that T he wants. This rules out the runtime error I have mentioned earlier.
You will still need asInstanceOf cast though. To avoid casting completely you will have to move VehicleReader instantiation code (e.g. yours new CarReader()) to VehicleType, because the only place where you know real value of VehicleType[T] type parameter is where instances of this type are constructed:
sealed trait VehicleType[T <: Vehicle] {
def newReader: VehicleReader[T]
}
object VehicleType {
case object Car extends VehicleType[Car] {
def newReader = new CarReader
}
// ... and so on
}
Then VehicleReader factory method will then look very clean and be completely typesafe:
object VehicleReader {
def apply[T <: Vehicle](vehicleType: VehicleType[T]) = vehicleType.newReader
}
I'm working on a DSL for a experimental library I'm building in Scala, and I've run into some vexing peculiarities of Scala's type inference as it pertains to lambda expression arguments that don't seem to be covered in the book Programming In Scala.
In my library, I have a trait, Effect[-T], that is used to represent temporary modifiers that can be applied to an object of type T. I have a object, myEffects, that has a method named += that accepts an argument of type Effect[PlayerCharacter]. Lastly, I have a generic method, when[T], that is used for constructing conditional effects by accepting a conditional expression and another effect as an argument. The signature is as follows:
def when[T](condition : T => Boolean) (effect : Effect[T]) : Effect[T]
When I call the "when" method with the above signature, passing it's result to the += method, it is unable to infer the type of the argument to the lambda expression.
myEffects += when(_.hpLow()) (applyModifierEffect) //<-- Compiler error
If I combine the arguments of "when" into a single parameter list, Scala is able to infer the type of the lambda expression just fine.
def when[T](condition : T => Boolean, effect : Effect[T]) : Effect[T]
/* Snip */
myEffects += when(_.hpLow(), applyModifierEffect) //This works fine!
It also works if I remove the second parameter entirely.
def when[T](condition : T => Boolean) : Effect[T]
/* Snip */
myEffects += when(_.hpLow()) //This works too!
However, for aesthetic reasons, I really want the the arguments to be passed to the "when" method as separate parameter lists.
My understanding from section 16.10 of Programming in Scala is that the compiler first looks at whether the method type is known, and if so it uses that to infer the expected type of it's arguments. In this case, the outermost method call is +=, which accepts an argument of type Effect[PlayerCharacter]. Since the return type of when[T] is Effect[T], and the method to which the result is being passed expects an argument of type Effect[PlayerCharacter], it can infer that T is PlayerCharacter, and therefore the type of the lambda expression passed as the first argument to "when" is PlayerCharacter => Boolean. This seems to be how it works when the arguments are provided in one parameter list, so why does breaking the arguments into two parameter lists break it?
I'm relatively new to Scala myself, and I don't have a lot of detailed technical knowledge of how the type inference works. So best take this with a grain of salt.
I think the difference is that the compiler is having trouble proving to itself that the two Ts are the same in condition : T => Boolean and effect : Effect[T], in the two-parameter-list version.
I believe when you have multiple parameter lists (because Scala views this as defining a method which returns a function that consumes the next parameter list) the compiler treats the parameter lists one at a time, not all together as in the single parameter list version.
So in this case:
def when[T](condition : T => Boolean, effect : Effect[T]) : Effect[T]
/* Snip */
myEffects += when(_.hpLow(), applyModifierEffect) //This works fine!
The type of applyModifierEffect and the required parameter type of myEffects += can help constrain the parameter type of _.hpLow(); all the Ts must be PlayerCharacter. But in the following:
myEffects += when(_.hpLow()) (applyModifierEffect)
The compiler has to figure out the type of when(_.hpLow()) independently, so that it can check if it's valid to apply it to applyModifierEffect. And on its own, _.hpLow() doesn't provide enough information for the compiler to deduce that this is when[PlayerCharacter](_.hpLow()), so it doesn't know that the return type is a function of type Effect[PlayerCharacter] => Effect[PlayerCharacter], so it doesn't know that it's valid to apply that function in that context. My guess would be that the type inference just doesn't connect the dots and figure out that there is exactly one type that avoids a type error.
And as for the other case that works:
def when[T](condition : T => Boolean) : Effect[T]
/* Snip */
myEffects += when(_.hpLow()) //This works too!
Here the return type of when and its parameter type are more directly connected, without going through the parameter type and the return type of the extra function created by currying. Since myEffects += requires an Effect[PlayerCharacter], the T must be PlayerCharacter, which has a hpLow method, and the compiler is done.
Hopefully someone more knowledgeable can correct me on the details, or point out if I'm barking up the wrong tree altogether!
I am a little confused because in my view, none of the versions you say work should, and indeed I cannot make any of them work.
Type inferences works left to right from one parameter list (not parameter) to the next. Typical example is method foldLeft in collections (say Seq[A])
def foldLeft[B] (z: B)(op: (B, A) => B): B
The type of z will makes B known, so op can be written without specifying B (nor A which is known from the start, type parameter of this).
If the routine was written as
def foldLeft[B](z: B, op: (B,A) => B): B
or as
def foldLeft[B](op: (B,A) => B)(z: B): B
it would not work, and one would have to make sure op type is clear, or to pass the B explicity when calling foldLeft.
In your case, I think the most pleasant to read equivalent would be to make when a method of Effect, (or make it look like one with an implicit conversion) you would then write
Effects += applyModifierEffect when (_.hpLow())
As you mentionned that Effect is contravariant, when signature is not allowed for a method of Effect (because of the T => Boolean, Function is contravariant in its first type parameter, and the condition appears as a parameter, so in contravariant position, two contravariants makes a covariant), but it can still be done with an implicit
object Effect {
implicit def withWhen[T](e: Effect[T])
= new {def when(condition: T => Boolean) = ...}
}
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.