The author of the question
Exchanging type parameters with abstract types wrote a => at the beginning of his class definitions. Example:
abstract class Thing { t =>
type A
type G <: Group { type A = t.A }
val group: G
}
What does the t => mean ?
Because this is hard to find in Google & Co, can someone please give me more background information or provide a link, where I can find more information about this language construct ?
The default naming for class itself is this. You may replace it with t by t =>
It is useful if your class contains subclasses and you need access to enclosing self reference.
Without t => in your example you would write something like this:
abstract class Thing {
type G <: Group { type A = this.A }
}
Group { type A = this.A } is a subtype so this would reference to group specialization itself not to a thing object. Probably you get not what you mean to get. If you need access to Thing self reference you should resolve name conflict by assigning self reference another name
abstract class Thing { another_this = >
type G <: Group { type A = another_this.A}
}
It is indeed self type annotation. See the official Scala specification:
https://scala-lang.org/files/archive/spec/2.13/13-syntax-summary.html
According to this specification, its context free EBNF syntax is:
SelfType ::= id [‘:’ Type] ‘=>’
| ‘this’ ‘:’ Type ‘=>’
So, basically, this means SelfType has two basic forms. In one form, you can use an id with or without Type. In the other, you can use this but it must be accompanied with a Type.
You can find it in section 29.4 of Programming in Scala Second Edition. However, remember that books can be quickly out of date, so you need to refer to the specification.
Related
I am reading in dread what will come with Scala 3, paying particular attention to changes to compound types. They were always somewhat of a hack, so clean, true intersection types are certainly an improvement. I couldn't find though anything about what happens to the actual refinement part of the compound type. I rely heavily in my current project on strongly interwoven types in an attempt to have every returned value be as narrow as possible. So, for example, having
trait Thing { thisThing =>
type A
type B
type C
def something :Thing {
type A = <related to thisThing.A>
type B <: <related to thisThing.B>
type C = <etc>
}
Is it even still possible? How to achieve this goal with the new semantics? As I understand, refinements of abstract types will almost certainly be not allowed, so it will be difficult to have a 'self type' declaration in a root of a type hierarchy:
trait Thing {
type ThisThing <: Thing
type A
type B
def copy(...) :ThisThing { type A = ...; type B = ... }
}
On a somewhat related note, I was looking at structural types. I must say I like how we can dynamic member selection/implementation with static declarations. Is it though possible for abstract classes? Could I write something like:
trait Record(members :(String, Any)*) extends Selectable { ... }
val r = new Record { val name :String; val age :Int }
EDIT: I found the relative bit of documentation and it looks like anonymous Selectable instance are exempt from the rule that the type of an anonymous class is the intersection of its extended types - good.
As I understand, refinements of abstract types will almost certainly be not allowed...
type A <: {
type U
}
trait B {
type T <: A
}
object o extends B {
type T = A { type U = Int }
}
perfectly compiles.
https://scastie.scala-lang.org/Nbz3GxoaTSe3VhXZz406vQ
What is not allowed is type projections of abstract types T#U
trait B {
type T <: A
type V = T#U // B.this.T is not a legal path since it is not a concrete type
}
https://scastie.scala-lang.org/xPylqOOkTPK9CvWyDdLvsA
http://dotty.epfl.ch/docs/reference/dropped-features/type-projection.html
Maybe you meant that
type A {
type U
}
is not parseable. But in Scala 2 it isn't either. Correct is either
trait A {
type U
}
or
type A <: {
type U
}
I understand what the result of a self type is as in
trait SpellChecker {
self: RandomAccessSeq[char] =>
...
}
from http://www.markthomas.info/blog/92
As far as I understand it says "the object instantiated from this trait is also of type RandomAccessSeq[char]". Is that right?
My question: What can I write after the => and what does it mean? I noticed I don't get a compiler error when writing AnyRef after the =>.
My question: What can I write after the =>
Anything.
and what does it mean?
It denotes the end of the self-type annotation. After that comes the normal trait body, just like as if the self-type annotation wasn't even there.
trait A { ta: B =>
// code
}
In this example ta is a this alias. It's useful as a shorthand for A.this, for when you need to reference this code from somewhere else.
Because ta (i.e. this code) is of type B, all of B's methods and member data are in scope and freely available. This becomes a contract that the compiler will enforce: because A code can reference B code, A cannot be instantiated without B also in the mix.
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.
I am hitting a compiler problem when the compiler needs to solve a manifest for a class with an abstract type parameter. The following snippet show the issue
trait MyStuff
trait SecurityMutatorFactory[X]{
def apply(x1:X,x2:X)
}
object Example{
trait LEdge[N]
{
type L1
}
type MyEdge[X] = LEdge[X] { type L1 = SecurityMutatorFactory[X]}
val a:Manifest[MyEdge[MyStuff]] = implicitly[Manifest[MyEdge[MyStuff]]]
}
As a result, the compiler throws the following type error:
type mismatch;
found : scala.reflect.Manifest[LEdge[MyStuff]]
required: Manifest[MyEdge[MyStuff]]
Note: LEdge[MyStuff] >: MyEdge[MyStuff], but trait Manifest is invariant in type T.
You may wish to investigate a wildcard type such as `_ >: MyEdge[MyStuff]`. (SLS 3.2.10)
val a:Manifest[MyEdge[MyStuff]] = implicitly[Manifest[MyEdge[MyStuff]]]
What is happening at compiler level? ^
As others have suggested the problem comes from
type MyEdge[X] = LEdge[X] { type L1 = SecurityMutatorFactory[X] }
Declarations of the form type F[X] = ... introduce type synonyms, ie new names for existing types. They do not construct new traits or classes. However, LEdge[X] { type L1 = SecurityMutatorFactory[X] } is constructing a new anonymous class. So your example is approximatelly equivalent to
trait MyEdge[X] extends LEdge[X] { type L1 = SecurityMutatorFactory[X] }
(which is what you most probably want) but the original definition in the example is defining a synonym for an anonymous class instead of defining a new class MyEdge[X]. So in the example the new class is not actually called MyEdge. When constructing the implicit manifest, the compiler replaces the type synonym with the underlying type, but fails to construct a manifest for that because that type is anonymous.
Replacing the MyEdge declaration with either a normal extension definition:
trait MyEdge[X] extends LEdge[X] { type L1 = SecurityMutatorFactory[X] }
or with an ordinary type synonym:
type MyEdge[X] = LEdge[X]
both compile successfully.
EDIT
Here is the specific reason why generating implicit manifests for anonymous classes fails.
In the language specification type expessions of the form BaseType { ... } are called refined types.
According to the language specification, the manifest for a refined type is just the manifest of its base class. This however fails to typecheck, because you asked for a Manifest[LEdge[MyStuff]{ type L1 = SecurityMutatorFactory[X] }], but the algorithm is returning Manifest[LEdge[MyStuff]]. This means that you can only construct implicit manifests for types with refined types only in contravariant positions. For example using:
type MyEdge[X] = LEdge[X] { type L1 = SecurityMutatorFactory[X] } => AnyRef
in your example allows it to compile, though it is clearly not what you are after.
The full algorithm for constructing implicit manifests is given at the end of section 7.5 of the language specification. This question is covered by clause 6:
6) If T is a refined type T'{R}, a manifest is generated for T'. (That is, refinements are never reflected in manifests).
Well, I'm not so familiar with that kind of pattern:
type MyEdge[X] = LEdge[X] { type L1 = SecurityMutatorFactory[X]}
but I tend to consider types defined with the type keyword as aliases (concepts) rather than a guarantee about the implementation (EDIT more precisely, I believe that type provides guarantees in terms of prototyping/specifying but that no AST/code is generated until there's an actual need to replace the alias with the traits/classes it's based upon). So even if the compiler claims, in its error message:
LEdge[MyStuff] >: MyEdge[MyStuff]
I'm not sure that, at the bytecode level, it implements MyEdge accordingly, with interfaces/methods/etc. Thus, it might not recognize the wanted relationship between LEdge and MyEdge, eventually:
found : scala.reflect.Manifest[LEdge[MyStuff]]
required: Manifest[MyEdge[MyStuff]]
(and, is the absence of package scala.reflect. a hint? (1))
About your code, how do you use a? Anyway, if the following is your intent, with:
trait MyEdge[X] extends LEdge[X] {
type L1 = SecurityMutatorFactory[X]
}
instead, it does compile (scala 2.10)... (EDIT I just noticed now that dmitry already told that) ...what that does during runtime, I don't know!
As an item of note, Manifest is deprecated after scala 2.9; so you may prefer to use TypeTag[T] as described in the scaladoc.
EDIT:
(1) I suspect that the following happens:
- at the syntactic analysis phase, the compiler registers literally what you specified, that is, the implicitly method shall return a Manifest[MyEdge[MyStuff]].
- by the code generation phase, the aliases are "reconciled" to their nearest classes or traits; in the case of implicitly the result's type Manifest[MyEdge[MyStuff]] becomes trait scala.reflect.Manifest[LEdge[MyStuff]]]
- due to some limitations of type inference involved in Manifest and type "aliasing" within type parameters, however, somehow the specified requirement Manifest[MyEdge[MyStuff]] remains under its raw shape
- (this is pure conjecture, because I've not read the Scala compiler source code for this answer) the compiler would have the proper AST/code on the one hand, but a method prototype/spec that is still under its raw/literal shape on the other hand; that doesn't fit in so it emits an error.
Hoping that helps...
Is it possible to create, in Scala, a type which is parametrized by a value? Instead of defining a partial type List[A] and parametrize it with List[Int], I'd like to define a partial type (in pseudo-code) Element[Symbol] and parametrize it with Element['td]. In this example, the type represent an XML element: Element['td] informs the Scala type checker that we have a <td> element, and you can imagine that one could have APIs that specifically expect or return <td> elements.
(Subclassing, as inclass Td extends Element, is not a very satisfactory solution, as it doesn't prevent two pieces of code, maybe written by independent developers, from declaring different subclasses for <td>, which will then be considered to be different types by the Scala type checker.)
If you really want to parameterize a type by a value, you need a dependently typed programming language such as Agda.
Just some ideas to play with... Objects are values and they have a type.
trait XmlElement
object Td extends XmlElement
Then, you can have a parameterized class and use it on that specific type.
class Element[T <: XmlElement] { ... }
val elementOnTd = new Element[Td.type]
// elementOnTd can only be used with Td.
If there is only a fixed number of elements you want to support then you can make a sealed trait and your library will only work with those objects (though that seems pretty limiting)
sealed trait XmlElement
object Td extends XmlElement
object Tr extends XmlElement
// can't have anything other than `Td` and `Tr` !
The other thing you can play with is that inner classes of objects don't have the same type. So you can also do something along the line object Td { class Element { ... } } and Td.Element won't have the same type as Tr.Element.
It sounds like what you really want is not so much to parameterize a type by a value (like you could in C++) but to force various developers to agree on a common implementation.
I don't think that that is a problem the language would solve for you. Even if you force there to only be one way to have a <td> type, isn't there still discretion in what, exactly, that <td> type is?
If you really do want to parameterize a type by a value, you'll probably have to do something like:
object TD {
}
ie make it actually be a type, now you can write Element[TD]. Though that still has the problem that someone else could write object TD { } in another package and there'd be two of them.
You could try and emulate full dependent types using something like
object A { }
object B { }
object C { }
...
object TyString[Car,Cdr] { }
So that "TD" would be represented as
TyString[T,TyString[D,()]]
But you probably don't want to go there ;)
(I've heard that Scala was going to implement something called "singleton literals", but did that ever happen? You were supposed to be able to write "td".type, but Scala 2.9.1 doesn't accept that syntax).
Singleton types will give you want you're asking for,
scala> class Element[+T]
defined class Element
scala> val td = 'td
td: Symbol = 'td
scala> val p = 'p
p: Symbol = 'p
scala> def acceptAll[T](e : Element[T]) = e
acceptAll: [T](e: Element[T])Element[T]
scala> def acceptTd(e : Element[td.type]) = e
acceptTd: (e: Element[td.type])Element[td.type]
scala> acceptAll(new Element[p.type]) // OK
res3: Element[Symbol] = Element#628b54f4
scala> acceptAll(new Element[td.type]) // OK
res4: Element[Symbol] = Element#6e7eee36
scala> acceptTd(new Element[td.type]) // OK
res2: Element[td.type] = Element#547fa706
scala> acceptTd(new Element[p.type]) // Doesn't compile
<console>:12: error: type mismatch;
found : Element[p.type]
required: Element[td.type]
acceptTd(new Element[p.type])
^
However, they're not giving you anything you couldn't already have had by creating a (sealed) family of types to represent element names. Note that there's nothing special about the use of Scala Symbols here: any stable identifier of a reference type gives rise to a unique singleton type which can be used in the same way.