Implement a macro in superclass and expand it in subclasses - scala

I want to do something like this:
trait Endo {
def apply[T](x: T): T
}
trait SuperType {
def endoMap(f: Endo): SuperType = macro SuperTypeMacro.endoMapImpl
}
case class Foo(x: Int) extends SuperType {
// endoMapImpl expands to
// Foo(f(x))
}
case class Bar(x: Int, y: Boolean) extends SuperType {
// endoMapImpl expands to
// Bar(f(x), f(y))
}
Ideally the only thing I would need to write is extends SuperType. Is it possible? If not, I believe macro annotations should allow this; am I right?

I think what you're looking for is c.prefix, that contains the receiver of the current macro method call. Once you get hold of it, you can branch on its type.

Related

variances and bounds together

What I need is, let say, I have a List trait, and Value trait, and special lists store special Value types. I tried this, but line.value doesn't exist, and the reason is, it looks like prepend's type parameter is not the actual SingleValue class, but it is still a template. But why? thanks
sealed trait Value
case class SingleValue(value: Int) extends Value
case class DoubleValue(value1: Int, value2: Int) extends Value
trait List1 {
def prepend[B <: Value](value: B): Int
}
case class SingleList1 extends List1 {
def prepend[SingleValue](line: SingleValue): Int = {
line.value
}
}
SingleValue in def prepend[SingleValue](line: SingleValue) is a type parameter, not a concrete type.
Like when you wrote def prepend[B <: Value](value: B): Int, you used B as a variable def prepend[SingleValue] has exactly the same meaning (except that variable name is different, but that's immaterial).
It is not very clear from your question what exactly you are trying to do here ... but, if I am guessing correctly, you want to parametrize the class, not the method:
trait List1[B <: Value] {
def prepend(b: B): Int
}
class SingleList extends List1[SingleValue] {
def prepend(sv: SingleValue) = sv.value
}
Update So, if you want your List1 to be covariant, as you mentioned in the comment, that won't work: if it did, then SingleList would be a subclass of List1[Value], and therefore prepend would have to work with any Value, not just SingleValue, and it doesn't know how.
What you could do in that case, is define the specialized prepend method "on the side" and associate it with List1 via an implicit conversion:
trait Lis1[+B <: Value]
object List1Ops {
implicit class SVL[T <: SingleValue](val l: List1[T]) extends AnyVal {
def prepend(v: T) = v.value
}
}
This let's you do both things like:
val svl = new List1[SingleValue]{}
println(svl.prepend(new SingleValue))
and
val l: List1[Value] = new List1[SingleValue]{} // still covariant
Is that what you are after?

Enforce that all subclasses implement a given type class

Given a superclass or trait, and assuming an open hierarchy, how can I enforce that all extending classes implement a particular type class?
For instance, assuming the type class Default
trait Default[T] { def default: T }
and some trait Super:
trait Super { }
I would like to enforce that the following (by itself) is not allowed:
class A(val i: Int) extends Super
...while the following is:
class B(val i: Int) extends Super
implicit val bHasDef = new Default[B] { def default = B(42) }
Assuming the above is possible, can I then access the type class evidence for the subtypes from a method within Super? I.e, something like:
trait Super {
def magic: Default[this.type] = ???
}
I hardly think you can enforce that, at least in a simple enough way, maybe it's possible with something more complex like shapeless.
What I would do is add some modifications to the super trait and make it take a self reference to Default
trait Default[T] { def default: T }
trait Super[T] {
self: Default[T] =>
}
class B(val i: Int) extends Super[Int] with Default[Int] {
override def default: Int = ???
}
class A(val i: Int) extends Super[Int] // doesn't compile, needs a Default
This should also solve the second part of your question, the disadvantage is that now one trait is bundled to the other.

Scala: illegal inheritance; self-type Foo[T] does not conform to Foo[T]'s selftype T

I have the following code snippet:
abstract class Foo[T <: Foo[T]] { self: T =>
def bar(x: T): T
def newFoo: Foo[T] = {
new Foo[T] { self: T =>
// ...
}
}
}
I have a need to generate a new instance of Foo within a method of my abstract class. Can anyone advise me on how best to approach this?
Thanks,
Hadil
The self-type self: T => implies that your Foo[T] must also be a T. new Foo[T] { ... } isn't an instance of T for any arbitrary T that makes up Foo[T]. You also can't add a self-type to an anonymous class like new Foo[T] { ... }, because it doesn't make sense. Either the concrete class is or isn't a T at that point.
Constructing a method like def newFoo: Foo[T] in a type-safe way isn't really possible with the self-type in place, because you'd need to know how to construct an arbitrary T. You might be able to do what you want with reflection, when each T has the same constructor.
import scala.reflect._
abstract class Foo[T <: Foo[T] : ClassTag] { self: T =>
def bar(x: T): T
def newFoo: Foo[T] = classTag[T].runtimeClass.newInstance.asInstanceOf[T]
}
class Bar extends Foo[Bar] {
def bar(x: Bar): Bar = x
}
scala> val b = new Bar
b: Bar = Bar#2a2d45ba
scala> b.newFoo
res1: Foo[Bar] = Bar#146ba0ac
This ceases to work when there are constructor parameters:
case class Baz(i: Int) extends Foo[Baz] {
def bar(x: Baz): Baz = x
}
scala> val baz = new Baz(0)
baz: Baz = Baz(0)
scala> baz.newFoo
java.lang.InstantiationException: Baz
at java.lang.Class.newInstance(Class.java:427)
at Foo.newFoo(<console>:16)
Well, you do not know the concrete class where Foo will be inherited in the future. So especially, you do not know which constructor parameters this class will have and how to supply arguments for them. If you really would want to do this, you would have to make some assumptions (that you cannot enforce at compile time) to achieve this.
So what you probably should do, is, leave this method abstract and implement it in a subclass. If this is not an option, you probably have some issues with your overall class design. Better present here what you want to model and ask for help.
If you assume, that the constructor of the concrete class won't have any parameters, you can implement newFoo just as
def newFoo = this.getClass.newInstance
There is no need for classTags or other fancy stuff.

Scala: implementing method with return type of concrete instance

I need a way to enforce a method in an abstract class to have a return type of the concrete class of the object it is called on. The most common example is a copy() method, and I'm currently using an approach based on abstract types:
abstract class A(id: Int) {
type Self <: A
def copy(newId: Int): Self
}
class B(id: Int, x: String) extends A(id) {
type Self = B
def copy(newId: Int) = new B(newId, x)
}
class C(id: Int, y: String, z: String) extends A(id) {
type Self = C
def copy(newId: Int) = new C(newId, y, z)
}
I already saw many approaches, including the ones in this great answer. However, none of them really forces a implementation to return its own type. For example, the following classes would be valid:
class D(id: Int, w: String) extends A(id) {
type Self = A
def copy(newId: Int) = new D(newId, w) // returns an A
}
class E(id: Int, v: String) extends A(id) {
type Self = B
def copy(newId: Int) = new B(newId, "")
}
The fact that I can do that causes that, if I am doing copies of objects of which the only information I have is that they are of a given subclass of A's:
// type error: Seq[A] is not a Seq[CA]!
def createCopies[CA <: A](seq: Seq[CA]): Seq[CA] = seq.map(_.copy(genNewId()))
Is there a better, type-safe way I can do that?
EDIT: If possible, I would like to keep the ability to create arbitrarily deep hierarchies of abstract classes. That is, in the previous example, I'm expecting to be able to create an abstract class A2 that extends A, and then proceed to create A2's concrete subclasses. However, if that simplifies the problem (as it's the case with abstract types), I do not need to further extend already concrete classes.
The only solution I could think of was this one:
trait CanCopy[T <: CanCopy[T]] { self: T =>
type Self >: self.type <: T
def copy(newId: Int): Self
}
abstract class A(id: Int) { self:CanCopy[_] =>
def copy(newId: Int): Self
}
The following would compile:
class B(id: Int, x: String) extends A(id) with CanCopy[B] {
type Self = B
def copy(newId: Int) = new B(newId, x)
}
class C(id: Int, y: String, z: String) extends A(id) with CanCopy[C] {
type Self = C
def copy(newId: Int) = new C(newId, y, z)
}
The following would not compile:
class D(id: Int, w: String) extends A(id) with CanCopy[D] {
type Self = A
def copy(newId: Int) = new D(newId, w) // returns an A
}
class E(id: Int, v: String) extends A(id) with CanCopy[E] {
type Self = B
def copy(newId: Int) = new B(newId, "")
}
Edit
I actually forgot to remove the copy method. This might be a bit more generic:
trait StrictSelf[T <: StrictSelf[T]] { self: T =>
type Self >: self.type <: T
}
abstract class A(id: Int) { self:StrictSelf[_] =>
def copy(newId:Int):Self
}
Do not force the type bound on the declaration side, unless you need that bound within the definition of A itelf. The following is sufficient:
abstract class A(id: Int) {
type Self
def copy(newId: Int): Self
}
Now force the Self type on the use site:
def genNewId(): Int = ???
def createCopies[A1 <: A { type Self = A1 }](seq: Seq[A1]): Seq[A1] =
seq.map(_.copy(genNewId()))
I don't think it's possible in scala to do what you want.
If I were to:
class Base { type A }
class Other extends Base
class Sub extends Other
Now... we want type A to refer to "the type of the subclass."
You can see that from the context of Base, it's not particularly clear (from the compiler's perspective) what the specific "type of the subclass" means, nevermind what the syntax would be to refer to it in the parent. In Other it would mean an instance of Other, but in Sub it might mean an instance of Sub? Would it be OK to define an implementation of your method returning an Other in Other but not in Sub? If there are two methods returning A's, and one is implemented in Other and the other in Sub, does that mean the type defined in Base has two different meanings/bounds/restrictions at the same time? Then what happens if A is referred to outside of these classes?
The closest thing we have is this.type. I'm not sure if it would be theoretically possible to relax the meaning of this.type (or provide a more relaxed version), but as implemented it means a very specific type, so specific that the only return value satisfying def foo:this.type is this itself.
I'd like to be able to do what you suggest, but I'm not sure how it would work. Let's imagine that this.type meant... something more general. What would it be? We can't just say "any of the defined types of this," because you wouldn't want class Subclass with MyTrait{type A=MyTrait} to be valid. We could say "a type satisfying all of the types of this," but it gets confusing when someone writes val a = new Foo with SomeOtherMixin... and I'm still not sure it could be defined in a way that would enable an implementation of both Other and Sub defined above.
We're sort-of trying to mix static and dynamically defined types.
In Scala, when you say class B { type T <: B }, T is specific to the instance, and B is static (I'm using that word in the sense of static methods in java). You could say class Foo(o:Object){type T = o.type}, and T would be different for every instance.... but when you write type T=Foo, Foo is the statically specified type of the class. You could just as well have had an object Bar, and had referred to some Bar.AnotherType. The AnotherType, since it's essentially "static," (though not really called "static" in Scala), doesn't participate in inheritance in Foo.
However, none of them really forces a implementation to return its own type. For example, the following classes would be valid.
But isn't it normal? Otherwise it would mean that you could not merely extend A to add a new method by example, as it would automatically break the contract that you are trying to create (that is, the new class's copy would not return an instance of this class, but of A).
The very fact of being able to have a perfectly fine class A that breaks as soon as you extend it as class B feels wrong to me.
But to be honest I have trouble putting words on the problems it causes.
UPDATE: After thinking a bit more about this, I think this could be sound if the type check ("return type == most-derived class") was made only in concrete classes and never on abstract classes or traits.
I am not aware of any way to encode that in the scala type system though.
The fact that I can do that causes that, if I am doing copies of objects of which the only information I have is that they are of a given subclass of A's
Why can't you just return a Seq[Ca#Self] ? By example, with this change passing a list of B to createCopies will as expected return a Seq[B] (and not just a Seq[A]:
scala> def createCopies[CA <: A](seq: Seq[CA]): Seq[CA#Self] = seq.map(_.copy(123))
createCopies: [CA <: A](seq: Seq[CA])Seq[CA#Self]
scala> val bs = List[B]( new B(1, "one"), new B(2, "two"))
bs: List[B] = List(B#29b9ab6c, B#5ca554da)
scala> val bs2: Seq[B] = createCopies(bs)
bs2: Seq[B] = List(B#92334e4, B#6665696b)

Defining implicit view-bounds on Scala traits

I'm doing an exercise to implement a functional binary-search-tree in Scala, following a similar pattern that I've seen used in Haskell. I have a structure that looks something like this:
trait TreeNode[A] {
def isLeaf: Boolean
def traverse: Seq[A]
...
}
case class Branch[A](value: A, left: TreeNode[A], right: TreeNode[A]) extends TreeNode[A] {
def isLeaf: Boolean = false
def traverse: Seq[A] = ...
...
}
case class Leaf[A]() extends TreeNode[A] {
def isLeaf: Boolean = true
def traverse: Seq[A] = Seq[A]()
...
}
I'd like to put a type constraint on A so that it will only accept objects that extend Ordered. It looks like I need to define a view bound on A ([A <% Ordered[A]]) on Branch and Leaf, as well as the TreeNode trait.. I can't do this on the TreeNode trait, however, because view bounds aren't accepted.
As I understand, <%-style view-bounds are syntactic sugar for an implicit definition, so there should be a way to write to define the bound manually within the TreeNode trait. I'm not sure how I'm supposed to do this, though. I've looked around a bit, but haven't gotten much further than that some sort of implicit needs to be defined.
Can anybody point me in the right direction? Am I approaching this from the wrong angle entirely?
The problem is that view bounds as well as context bounds are just syntactic sugar for specific types of implicit parameters. When applied to a type parameter of a generic class (as opposed to when applied to a generic method), these implicits are added to the constructor of the class.
Because traits have no constructor (or rather, only have a single parameterless constructor), there is nowhere to pass these implicit parameters and thus context bounds and view bounds are illegal on generic traits.
The simplest solution would be to turn TreeNode into an abstract class.:
abstract class TreeNode[A <% Ordered[A]]
Note that as advised by Ben James, using a context bound with an Ordering is usually better than a view bound with an Ordered (it is more general). However the problem is still the same: won't work on a trait.
If turning TreeNode into a class is not practical (say you need to mix it at various places in the type hierarchy), you can define an abstract method in TreeNode that will provide the implicit value (of type Ordered[A]) and have all the classes that extend it define it. This unfortunately more verbose and explicit, but you can't do much better in this case:
trait TreeNode[A] {
implicit protected def toOrdered: A => Ordered[A]
}
case class Branch[A<%Ordered[A]](value: A, left: TreeNode[A], right: TreeNode[A]) extends TreeNode[A] {
protected def toOrdered = implicitly[A => Ordered[A]]
}
case class Leaf[A<%Ordered[A]]() extends TreeNode[A] {
protected def toOrdered = implicitly[A => Ordered[A]]
}
Note that for a more concise definition, you could equivalently define Leaf like this:
case class Leaf[A](implicit protected val toOrdered: A => Ordered[A]) extends TreeNode[A]
You could provide the "evidence" that A is Ordered by requiring an abstract member of type Ordered[A] on the trait:
trait TreeNode[A] {
implicit val evidence: Ordered[A]
}
You would then be forced to provide this in any concrete subtypes, this proving that A is Ordered:
case class Leaf[A](value: A)(implicit ev: Ordered[A]) extends TreeNode[A] {
val evidence = ev
}
You might instead want to constrain A to a type which has an implicit Ordering[A] - this is not an inheritance relationship; it is more like a haskell typeclass. But the implementation in terms of the above technique would be the same.
#ben-james's answer is great, I would like improve it a bit to avoid redundant vals in classes.
The idea is to define implicit constructor parameter name the same as it is defined in trait that holds implicit value.
The idea is to avoid this line:
val evidence = ev
Here is a complete example (gist)
trait PrettyPrinted[A] extends (A => String)
object PrettyPrinted {
def apply[A](f: A => String): PrettyPrinted[A] = f(_)
}
trait Printable[A] {
implicit def printer: PrettyPrinted[A]
}
// implicit parameter name is important
case class Person(name: String, age: Int)
(implicit val printer: PrettyPrinted[Person])
extends Printable[Person]
object Person {
implicit val printer: PrettyPrinted[Person] =
PrettyPrinted { p =>
s"Person[name = ${p.name}, age = ${p.age}]"
}
}
// works also with regular classes
class Car(val name: String)
(implicit val printer: PrettyPrinted[Car])
extends Printable[Car]
object Car {
implicit val printer: PrettyPrinted[Car] =
PrettyPrinted { c =>
s"Car[name = ${c.name}]"
}
}