I'm trying to compile the following code, but the last line does not compile:
class SuperContainer (
val shapeSets: Set[MyContainer[Shape]] = Set.empty[MyContainer[Shape]]) {
def addAct(el: MyContainer[Shape]) = {
new SuperContainer(shapeSets + el)
}
}
class MyContainer[A](val ls: Set[A] = Set.empty[A]) {
def addElement(el: A) = {
new MyContainer(ls + el)
}
}
abstract class Shape
case class Circle(radius: Int) extends Shape {
override def toString = "Circle(" + radius + ")"
}
case class Square(s: Int) extends Shape {
override def toString = "Square(" + s + ")"
}
object MyContainer {
def main(args: Array[String]) {
//Circle Container
val myc1 = new MyContainer[Circle]()
val myc11 = myc1.addElement(new Circle(6))
//Square Container
val myc2 = new MyContainer[Square]()
val myc21 = myc2.addElement(new Square(6))
val scont = new SuperContainer
scont.addAct(myc11) //does not compile
}
}
Scala compiler suggests me to use +A in MyContainer class definition, but by doing that, other compile errors occur. Am I doing something wrong or this is just a Scala limitation? Is there any way to overcome this problem?
In order to achieve what you want, MyContainer has to be covariant:
class MyContainer[+A](val ls: Set[A] = Set.empty[A]) // ...
Now, your definition of addElement will cause an error, since A appears in contravariant position (as a function argument in this case). You will have to adapt your signature as follows:
def addElement[B >: A](el: B): MyContainer[B]
This makes sense if you think of it: If you have a Container[Circle] (which can be seen as a Container[Shape] due to covariance) and you add a Shape, you have a Container[Shape] at the end and not a Container[Circle].
The implementation of addElement will not change.
Further, you cannot make Set[A] available outside the class (i.e. you have to remove the val), since Set[A] is not covariant. If you want to access elements, you'll have to add additional methods to query the set.
class MyContainer[+A](ls: Set[A] = Set.empty[A]) // ...
UPDATE
This is to explain clearer, why Set[A] cannot be part of MyContainer[+A]'s public API. Say we have:
class A
class B extends A
Imagine the following:
val x: MyContainer[A] = new MyContainer[B]
We can do that due to the covariance. However, if we could call now:
val s = x.ls // get internal set
We expect s to be of type Set[A]. However, the internal Set of x is a Set[B] which is not a Set[A]. Therefore this is not correctly typed.
Related
Suppose I have a trait Foo with several methods. I want to create a new trait which extends Foo but "wraps" each method call, for example with some print statement (in reality this will be something more complicated / I have a couple of distinct use cases in mind).
trait Foo {
def bar(x: Int) = 2 * x
def baz(y: Int) = 3 * y
}
I can do this manually, by overriding each method. But this seems unnecessarily verbose (and all too easy to call the wrong super method):
object FooWrapped extends FooWrapped
trait FooWrapped extends Foo {
override def bar(x: Int) ={
println("call")
super.bar(x)
}
override def baz(y: Int) ={
println("call")
super.baz(y)
}
}
scala> FooWrapped.bar(3)
call
res3: Int = 6
I was hoping to write a mixin trait, that I would be able to reuse with other traits, and use as:
trait FooWrapped extends Foo with PrintCall
That way I don't have to manually override each method (the mixin would do this for me).
Is it possible to write such a mixin trait in Scala? What would it look like?
Update Here is the macro. It was much less painful than I thought it will be because of quasiquotes. They are awesome. This code does only a little and you probably will have to improve it. It may not account some special situations. Also it assumes that neither parent class nor it's method has type params, it wraps only the methods of the given class or trait, but not it's parents methods, it may not work if you have auxilary constructors etc. Still I hope it will give you an idea of how to do that for your specific needs, making it working for all of the situations unfortunately is too big job for me right now.
object MacrosLogging {
import scala.language.experimental.macros
import scala.reflect.macros.blackbox
def log_wrap[T](): T = macro log_impl[T]
def log_impl[T : c.WeakTypeTag](c: blackbox.Context)(): c.Expr[T] = {
import c.universe._
val baseType = implicitly[c.WeakTypeTag[T]].tpe
val body = for {
member <- baseType.declarations if member.isMethod && member.name.decodedName.toString != "$init$"
method = member.asMethod
params = for {sym <- method.paramLists.flatten} yield q"""${sym.asTerm.name}: ${sym.typeSignature}"""
paramsCall = for {sym <- method.paramLists.flatten} yield sym.name
methodName = member.asTerm.name.toString
} yield {
q"""override def ${method.name}(..$params): ${method.returnType} = { println("Method " + $methodName + " was called"); super.${method.name}(..$paramsCall); }"""
}
c.Expr[T] {q""" { class A extends $baseType { ..$body }; new A } """}
}
}
If you do not want to create an instance, but you do want to add logging only for your trait so you could mixin further, you can do this with relatively the same code, but using macro paradise type annotations: http://docs.scala-lang.org/overviews/macros/annotations These allow you to tag your class definitions and perform modifications right inside the definitions
You could do something like you want with Dynamic, but there is a catch - you can't make it of original type, so it's not a mixin. Dynamic starts to work only if type checks fails, so you can't mixin real type (or I do not know how to do that). The real answer would probably require macros (as #AlexeyRomanov suggested in comments), but I am not sure how to write one, maybe I'll come up with it later. Still Dynamic might work for you if you are not looking for DI here
trait Foo {
def bar(x: Int) = 2 * x
def baz(y: Int) = 3 * y
}
import scala.reflect.runtime.{universe => ru}
import scala.language.dynamics
trait Wrapper[T] extends Dynamic {
val inner: T
def applyDynamic(name: String)(args: Any*)(implicit tt: ru.TypeTag[T], ct: ClassTag[T]) = {
val im = tt.mirror.reflect(inner)
val method = tt.tpe.decl(ru.TermName(name)).asMethod
println(method)
val mm = im.reflectMethod(method)
println(s"$name was called with $args")
mm.apply(args:_*)
}
}
class W extends Wrapper[Foo] {
override val inner: Foo = new Foo() {}
}
val w = new W // Cannot be casted to Foo
println(w.bar(5)) // Logs a call and then returns 10
You can read more about Dynamic here: https://github.com/scala/scala/blob/2.12.x/src/library/scala/Dynamic.scala
As I understand the semantics of a custom constructor may be typically added to a class via a companion object. Is there then, any way to inherit a custom constructor while inheriting a class?
On the one hand I have found that companion objects are not synthetically inherited along a case class, and on the other, I am not aware of a way of creating custom constructors inside a class itself, so that they are inherited. And yet inheriting custom constructors seems to be a perfectly valid use case to me. So is it supported in some (straightforward) way in Scala?
A naive demonstration of intent:
class A {}
object A {
def apply(n: Int) = {
println(n)
new A
}
}
class B extends A {}
object Test {
val a1 = A
val a2 = A(3)
val b1 = B // compile error
val b2 = B(3) // compile error
P.S. I have even found the arcane/deviant technique of defining this custom constructors result in a custom constructor that does not in actuality get inherited (it does work for just creating custom constructors, but quite oddly and unfortunately those do not get inherited). Demonstrating code:
class A {
def this(n: Int) = {
this
println(n)
}
}
class B extends A {}
object Test {
val a1: A = new A
val a2: A = new A(3)
val b1 = new B
val b2 = new B(3) // compile error
}
Clarification of Intent Edit:
consider "constructor" and "companion factory methods" interchangeable for the sake of this question.
You can't inherit constructors directly, and because you can't you also can't inherit things that use them without a little bit of work. But you can abstract away anything beyond the constructor call.
Let's suppose we have
class Foo(text: String) {
override def toString = "Foo: " + text
}
object Foo {
def apply(text: String) = new Foo(text) // Auto-generated for case class
def apply(i: Int) = new Foo(
if (i > 0) i.toString
else if (i == 0) ""
else s"negative ${0L - i}"
)
}
and we then decide to
class Bar(text: String) extends Foo(text) {
override def toString = "Bar: " + text
}
Now, what do we do about object Bar? Instead of writing all the logic over again, we create a trait to separate and abstract the object creation from the computation of the constructor parameter(s):
trait FooCompanionLike[A <: Foo] {
def apply(text: String): A // I am abstract!
def apply(i: Int): A = apply(
if (i > 0) i.toString
else if (i == 0) ""
else s"negative ${0L - i}"
)
}
Now we can
object Foo extends FooCompanionLike[Foo] {
def apply(text: String) = new Foo(text)
}
object Bar extends FooCompanionLike[Bar] {
def apply(text: String) = new Bar(text)
}
So you can't completely escape boilerplate, but you can reduce it to extending from a trait and a single method call.
If you do it this way (where the abstract apply perfectly matches the constructor), you can even get case classes to work without manually defining the abstract apply method in the companion:
case class Baz(text: String) extends Foo(text) {
override def toString = "Baz: " + text
}
object Baz extends FooCompanionLike[Baz] {
// Nothing here! Auto-generated apply works!
}
Short answer: no straightforward way; try to workaround and resist the desire.
Constructors in Scala are defined in the body of the class and take parameters after the class name e.g.
class A(i: Int) {
println(i)
}
The println(i) in this case is the constructor logic. If you now extend A, like this:
class B(i: Int) extends A(i)
and instantiate B, val b1 = new B(2) you'll see that the constructor is indeed inherited.
As you've already found out, Scala allows you to define alternative constructors by defining functions called this. But these alternative constructors must call the primary constructor.
The way I understand it is that there is really only one constructor for any Scala class, the alternative constructors just filter into it. For example:
class A(x: Int, y: Int) {
// do some constructing!
def this(x: Int) = {
this(x, 1) // provide a default value for y
}
}
What I try to do is to come up with a case class which I can use in pattern matching which has exactly one field, e.g. an immutable set. Furthermore, I would like to make use of functions like map, foldLeft and so on which should be passed down to the set. I tried it as in the following:
case class foo(s:Set[String]) extends Iterable[String] {
override def iterator = s.iterator
}
Now if I try to make use of e.g. the map function, I get an type error:
var bar = foo(Set() + "test1" + "test2")
bar = bar.map(x => x)
found : Iterable[String]
required: foo
bar = bar.map(x => x)
^
The type error is perfectly fine (in my understanding). However, I wonder how one would implement a wrapper case class for a collection such that one can call map, foldLeft and so on and still receive an object of the case class. Would one need to override all these functions or is there some other way around?
Edit
I'm inclined to accept the solution of RĂ©gis Jean-Gilles which works for me. However, after Googling for hours I found another interesting Scala trait named SetProxy. I couldn't find any trivial examples so I'm not sure if this trait does what I want:
come up with a custom type, i.e. a different type than Set
the type must be a case class (we want to do pattern matching)
we need "delegate" methods map, foldLeft and so on which should pass the call to our actual set and return the resulting set wrapped arround in our new type
My first idea was to extend Set but my custom type Foo already extends another class. Therefore, the second idea was to mixin the trait Iterable and IterableLike. Now I red about the trait SetProxy which made me think about which is "the best" way to go. What are your thoughts and experiences?
Since I started learning Scala three days ago, any pointers are highly appreciated!
Hmm this sounds promissing to me but Scala says that variable b is of type Iterable[String] and not of type Foo, i.e. I do not see how IterableLike helps in this situation
You are right. Merely inheriting from IterableLike as shown by mpartel will make the return type of some methods more precise (such as filter, which will return Foo), but for others such as map of flatMap you will need to provide an appopriate CanBuildFrom implicit.
Here is a code snippet that does just that:
import collection.IterableLike
import collection.generic.CanBuildFrom
import collection.mutable.Builder
case class Foo( s:Set[String] ) extends Iterable[String] with IterableLike[String, Foo] {
override def iterator = s.iterator
override protected[this] def newBuilder: scala.collection.mutable.Builder[String, Foo] = new Foo.FooBuilder
def +(elem: String ): Foo = new Foo( s + elem )
}
object Foo {
val empty: Foo = Foo( Set.empty[String] )
def apply( elems: String* ) = new Foo( elems.toSet )
class FooBuilder extends Builder[String, Foo] {
protected var elems: Foo = empty
def +=(x: String): this.type = { elems = elems + x; this }
def clear() { elems = empty }
def result: Foo = elems
}
implicit def canBuildFrom[T]: CanBuildFrom[Foo, String, Foo] = new CanBuildFrom[Foo, String, Foo] {
def apply(from: Foo) = apply()
def apply() = new FooBuilder
}
}
And some test in the repl:
scala> var bar = Foo(Set() + "test1" + "test2")
bar: Foo = (test1, test2)
scala> bar = bar.map(x => x) // compiles just fine because map now returns Foo
bar: Foo = (test1, test2)
Inheriting IterableLike[String, Foo] gives you all those methods such that they return Foo. IterableLike requires you to implement newBuilder in addition to iterator.
import scala.collection.IterableLike
import scala.collection.mutable.{Builder, SetBuilder}
case class Foo(stuff: Set[String]) extends Iterable[String] with IterableLike[String, Foo] {
def iterator: Iterator[String] = stuff.iterator
protected[this] override def newBuilder: Builder[String, Foo] = {
new SetBuilder[String, Set[String]](Set.empty).mapResult(Foo(_))
}
}
// Test:
val a = Foo(Set("a", "b", "c"))
val b = a.map(_.toUpperCase)
println(b.toList.sorted.mkString(", ")) // Prints A, B, C
I have a class that takes an implicit parameter which is used by functions called inside class methods. I want to be able to either override that implicit parameter, or alternatively, have the implicit argument be copied from its source. As an example:
def someMethod()(implicit p: List[Int]) {
// uses p
}
class A()(implicit x: List[Int]) {
implicit val other = List(3) // doesn't compile
def go() { // don't want to put implicit inside here since subclasses that override go() have to duplicate that
someMethod()
}
}
The behavior I want is that someMethod() gets an implicit parameter that is some changed version of x, which was the class's implicit parameter. I want to be able to either mutate x without changing it for whatever passed it into A's constructor, or otherwise override it to a new value of my choosing. Both approaches don't seem to work. That is, it doesn't copy the list in the former case, and the compiler finds an ambiguous implicit value for the latter case. Is there a way to do this?
I realize that I can redefine the implicit value within go(), but this is not a good choice in my case because this class is subclassed numerous times, and I'd like to handle this implicit change in the base class only. So it doesn't necessarily need to go in the constructor, but it must be in a method other than go().
Introduce another wrapper type, simply to disambiguate:
// badly named, choose something domain-specific
case class ListHolder(theList: List[Int])
def someMethod()(implicit holder: ListHolder) {
val xs = holder.theList
// uses xs ...
}
class A()(implicit xs: List[Int]) {
implicit val other = ListHolder(42 :: xs) // compiles
def go() {
// xs is never considered for the implicit param to someMethod()
// because it's now the wrong type
}
}
This also makes the code more self-documenting, as it becomes blindingly obvious that the two implicits are not one and the same.
If you want to have zillions of implicits floating around that don't collide with each other, you can create a wrapper class that you can tag with marker traits for implicit usage. There are a variety of syntaxes you could use; here's one example:
object Example {
class Implication[A,B](val value: A) {
def apply[C](c: C) = new Implication[C,B](c)
}
object Implication {
def mark[B] = new Implication[Unit,B](())
implicit def implication_to_value[A,B](i: Implication[A,B]) = i.value
}
trait One {}
trait Two {}
implicit val x = Implication.mark[One]("Hello")
implicit val y = Implication.mark[Two]("Hi")
def testOne(implicit s: Implication[String,One]) = println(s: String)
def testTwo(implicit s: Implication[String,Two]) = println(s: String)
def testThree(s: String) = println("String is " + s)
def main(args: Array[String]) {
testOne
testTwo
testThree(x)
testThree(y)
}
}
Which works as you would hope:
scala> Example.main(Array())
Hello
Hi
String is Hello
String is Hi
Since you have to use a wrapper object, it's not super-efficient, but it can be very effective. (Or very confusing, given how much happens implicitly.)
This modification compiles. I changed x into a var:
class A()(implicit var x: List[Int]) {
def someMethod()(implicit p: List[Int]) {
// uses p
}
x = List(3)
def go() { // don't want to put implicit inside here since subclasses that override go() have to duplicate that
someMethod()
}
}
Suppose one wants to build a novel generic class, Novel[A]. This class will contain lots of useful methods--perhaps it is a type of collection--and therefore you want to subclass it. But you want the methods to return the type of the subclass, not the original type. In Scala 2.8, what is the minimal amount of work one has to do so that methods of that class will return the relevant subclass, not the original? For example,
class Novel[A] /* What goes here? */ {
/* Must you have stuff here? */
def reverse/* What goes here instead of :Novel[A]? */ = //...
def revrev/*?*/ = reverse.reverse
}
class ShortStory[A] extends Novel[A] /* What goes here? */ {
override def reverse: /*?*/ = //...
}
val ss = new ShortStory[String]
val ss2 = ss.revrev // Type had better be ShortStory[String], not Novel[String]
Does this minimal amount change if you want Novel to be covariant?
(The 2.8 collections do this among other things, but they also play with return types in more fancy (and useful) ways--the question is how little framework one can get away with if one only wants this subtypes-always-return-subtypes feature.)
Edit: Assume in the code above that reverse makes a copy. If one does in-place modification and then returns oneself, one can use this.type, but that doesn't work because the copy is not this.
Arjan linked to another question that suggests the following solution:
def reverse: this.type = {
/*creation of new object*/.asInstanceOf[this.type]
}
which basically lies to the type system in order to get what we want. But this isn't really a solution, because now that we've lied to the type system, the compiler can't help us make sure that we really do get a ShortStory back when we think we do. (For example, we wouldn't have to override reverse in the example above to make the compiler happy, but our types wouldn't be what we wanted.)
Edit: I just realized that Rex had a concrete class Novel in his example, not a trait as I've used below. The trait implementation is a bit too simple to be a solution to Rex's question, therefore. It can be done as well using a concrete class (see below), but the only way I could make that work is by some casting, which makes this not really 'compile time type-safe'. This So this does not qualify as a solution.
Perhaps not the prettiest, but a simple example using abstract member types could be implemented as follows:
trait Novel[A] {
type T <: Novel[A]
def reverse : T
def revrev : T#T = reverse.reverse
}
class ShortStory[A](var story: String) extends Novel[A] {
type T = ShortStory[A]
def reverse : T = new ShortStory[A](story reverse)
def myMethod: Unit = println("a short story method")
}
scala> val ss1 = new ShortStory[String]("the story so far")
ss1: ShortStory[String] = ShortStory#5debf305
scala> val ssRev = ss1 reverse
ssRev: ss1.T = ShortStory#5ae9581b
scala> ssRev story
res0: String = raf os yrots eht
scala> val ssRevRev = ss1 revrev
ssRevRev: ss1.T#T = ShortStory#2429de03
scala> ssRevRev story
res1: String = the story so far
scala> ssRevRev myMethod
a short story method
It's certainly minimal, but I doubt whether this would enough to be used as a kind of framework. And of course the types returned not anywhere near as clear as in the Scala collections framework, so perhaps this might be a bit too simple. For the given case, it seems to do the job, however. As remarked above, this does not do the job for the given case, so some other solution is required here.
Yet Another Edit: Something similar can be done using a concrete class as well, though that also not suffices to be type safe:
class Novel[A](var story: String) {
type T <: Novel[A]
def reverse: T = new Novel[A](story reverse).asInstanceOf[T]
def revrev : T#T = reverse.reverse
}
class ShortStory[A](var s: String) extends Novel[A](s) {
type T = ShortStory[A]
override def reverse : T = new ShortStory(story reverse)
def myMethod: Unit = println("a short story method")
}
And the code will work as in the trait example. But it suffers from the same problem as Rex mentioned in his edit as well. The override on ShortStory is not necessary to make this compile. However, it will fail at runtime if you don't do this and call the reverse method on a ShortStory instance.
I haven't thought this through fully, but it type checks:
object invariant {
trait Novel[A] {
type Repr[X] <: Novel[X]
def reverse: Repr[A]
def revrev: Repr[A]#Repr[A]
= reverse.reverse
}
class ShortStory[A] extends Novel[A] {
type Repr[X] = ShortStory[X]
def reverse = this
}
val ss = new ShortStory[String]
val ss2: ShortStory[String] = ss.revrev
}
object covariant {
trait Novel[+A] {
type Repr[X] <: Novel[_ <: X]
def reverse: Repr[_ <: A]
def revrev: Repr[_ <: A]#Repr[_ <: A] = reverse.reverse
}
class ShortStory[+A] extends Novel[A] {
type Repr[X] = ShortStory[X]
def reverse = this
}
val ss = new ShortStory[String]
val ss2: ShortStory[String] = ss.revrev
}
EDIT
The co-variant version can be much nicer:
object covariant2 {
trait Novel[+A] {
type Repr[+X] <: Novel[X]
def reverse: Repr[A]
def revrev: Repr[A]#Repr[A] = reverse.reverse
}
class ShortStory[+A] extends Novel[A] {
type Repr[+X] = ShortStory[X]
def reverse = this
}
val ss = new ShortStory[String]
val ss2: ShortStory[String] = ss.revrev
}
After discussions on the Scala mailing list--many thanks to the people there for setting me on the right track!--I think that this is the closest that one can come to a minimal framework. I leave it here for reference, and I'm using a different example because it highlights what is going on better:
abstract class Peano[A,MyType <: Peano[A,MyType]](a: A, f: A=>A) {
self: MyType =>
def newPeano(a: A, f: A=>A): MyType
def succ: MyType = newPeano(f(a),f)
def count(n: Int): MyType = {
if (n<1) this
else if (n==1) succ
else count(n-1).succ
}
def value = a
}
abstract class Peano2[A,MyType <: Peano2[A,MyType]](a: A, f: A=>A, g: A=>A) extends Peano[A,MyType](a,f) {
self: MyType =>
def newPeano2(a: A, f: A=>A, g: A=>A): MyType
def newPeano(a: A, f: A=>A): MyType = newPeano2(a,f,g)
def pred: MyType = newPeano2(g(a),f,g)
def uncount(n: Int): MyType = {
if (n < 1) this
else if (n==1) pred
else uncount(n-1).pred
}
}
The key here is the addition of the MyType type parameter that is a placeholder for the type of the class that we'll really end up with. Each time we inherit, we have to redefine it as a type parameter, and we have add a constructor method that will create a new object of this type. If the constructor changes, we have to create a new constructor method.
Now when you want to create a class to actually use, you only have to fill in the constructor method with a call to new (and tell the class that it's of its own type):
class Peano2Impl[A](a: A, f: A=>A, g: A=>A) extends Peano2[A,Peano2Impl[A]](a,f,g) {
def newPeano2(a: A, f: A=>A, g: A=>A) = new Peano2Impl[A](a,f,g)
}
and you're off and running:
val p = new Peano2Impl(0L , (x:Long)=>x+1 , (y:Long)=>x-1)
scala> p.succ.value
res0: Long = 1
scala> p.pred.value
res1: Long = -1
scala> p.count(15).uncount(7).value
res2: Long = 8
So, to review, the minimal boilerplate--if you want to include recursive methods, which breaks the other style of answer--is for any methods that return a new copy from outside the class (using new or a factory or whatever) to be left abstract (here, I've boiled everything down to one method that duplicates the constructor), and you have to add the MyType type annotation as shown. Then, at the final step, these new-copy methods have to be instantiated.
This strategy works fine for covariance in A also, except that this particular example doesn't work since f and g are not covariant.