Consider following code in Scala:
object Test {
class A {}
class B extends A {}
class AI extends A {
def sayHello: String = "Hello from AI"
}
implicit def AtoAI(a: A): AI = a
class BI extends B {
def sayHello: String = "Hello from BI"
}
implicit def BtoBI(b: B): BI = b
def main(args: Array[String]) {
val a = new A
println(a.sayHello)
val b = new B
println(b.sayHello)
}
}
The use of implicits results in looping code. In fact, disassemblying reveals, that generated conversion methods have only a goto 0 inside:
public Test$AI AtoAI(Test$A);
Code:
0: goto 0
public Test$BI BtoBI(Test$B);
Code:
0: goto 0
What causes that behaviour? I understand, that a hierarchy of classes here is a suspect, but implicit conversion should be applied only once.
I use Scala 2.9.1
Not nice but I would definitely not call it a bug.
It boils down to
class A
class B
implicit def aToB(a: A) : B = a
There is no need for the two sides of the conversion to be related in any way. The implicit is just the same thing as writing
implicit def aToB(a: A): B = aToB(a)
because the compiler inserts the aToB call in order to convert the result a to the required return type B.
The goto 0 implementation is just a tail call optimization. The compiler might probably gives a warning when it generates a method that starts this way.
Maybe there could be a rule that implicit methods are not available as implicits inside their own body. But it does not always create an infinite loop
implicit def listAToListB(l: list[A] = l match {
case Nil => Nil
case x:xs => toB(x) :: xs // equivalent to toB(x) :: listAToList[B](xs)
}
(ok this is just a map(toB)). Anyway the same could happen with two mutually recursive implicits. In my opinion, it's not worthwhile to tweak the spec just to avoid some possibility to write an infinite, do nothing loop, among many others. But a warning when such a loop is detected, irrespective of implicits, would be nice.
I cannot understand why the code compiles at all. I verified that it does compile. Wouldn't you have to downcast inside the implicit conversion method?
Didier points out, that the implicit conversion gets applied recursively, which means the code can compile without a downcast.
The following code adds the downcasts (which should not change the runtime behavior). It fails at runtime with the failing casts. So this looks like a compiler bug to me. As Didier says, the explicit downcast prevents the recursive application of the implicit conversion here.
object Test {
class A {}
class B extends A {}
class AI extends A {
def sayHello: String = "Hello from AI"
}
implicit def AtoAI(a: A): AI = a.asInstanceOf[AI]
class BI extends B {
def sayHello: String = "Hello from BI"
}
implicit def BtoBI(b: B): BI = b.asInstanceOf[BI]
def main(args: Array[String]) {
val a = new A
println(a.sayHello)
val b = new B
println(b.sayHello)
}
}
Finishing by answering the question: you call a method of AI on an object of class A that doesn't have this method. Obviously this can't work. What happens is unspecified; in your case it was an infinite loop.
Related
Let's imagine I have the following base trait and case classes
sealed trait BaseTrait
case class Foo(x: Integer = 1) extends BaseTrait
case class Bar(x: String = "abc") extends BaseTrait
I would like to create a generic interface for classes which can process BaseTrait instances, something like the following
class FooProcessor(val model: FooModel) extends BaseProcessor[Foo] {
val v: Option[Foo] = model.baseVar
}
class BarProcessor(val model: BarModel) extends BaseProcessor[Bar] {
val v: Option[Bar] = model.baseVar
}
For this I have the following traits
trait BaseModel[T <: BaseTrait] {
var baseVar: Option[T] = None
}
trait BaseProcessor[T <: BaseTrait] {
def model: BaseModel[T]
def process(x: T): Unit = model.baseVar = Option(x)
}
The model definitions are the following
class FooModel extends BaseModel[Foo]
class BarModel extends BaseModel[Bar]
Now lets imagine I have the following processors somewhere in my app
val fooProcessor = new FooProcessor(new FooModel)
val barProcessor = new BarProcessor(new BarModel)
I would like to handle them in a somewhat generic way, like this
def func[T <: BaseTrait](p: T) {
val c/*: BaseProcessor[_ >: Foo with Bar <: BaseTrait with Product with Serializable]*/ = p match {
case _: Foo => fooProcessor
case _: Bar => barProcessor
c.process(p)
}
The compiler is not really happy about the last line, it says
type mismatch;
found : T
required: _1
If I understand correctly this is basically the compiler trying to prevent barProcessor.process(Foo()) from happening. I've tried a couple of solutions to get around this and achieve the desired behavior:
the simplest way around this is calling the proper *Processor.process with the proper BaseTrait instance inside the match case, which seems to defy the whole point of handling them in a somewhat generic way
use an abstract type in the BaseModel and BaseProcessor, which one hand got rid of the somewhat unneeded type parameter in BaseModel but the compilers complaint is still valid and I was not able to figure out if it's possible to get that to work
get rid of the type parameter and contraint from the BaseModel, and just do a type cast in the processor to get the proper type, but the explicit type cast also isn't really what I was hoping for
Like so:
trait BaseModel {
var baseVar: Option[BaseTrait] = None
}
trait BaseProcessor[T <: BaseTrait] {
def model: BaseModel
def process(x: T): Unit = model.baseVar = Some(x)
def getBaseValue: T = model.baseVar.map(_.asInstanceOf[T])
}
I guess one could also somehow convince the compiler that the two types (T of the Processor and T of the func parameter p) are equivalent, but that also seems like an overkill (and I'm also not really sure how it can be done).
So my question is the following: is it possible to do what I'm trying to achieve here (managing processors in a uniform way + each processor knows their specific type of BaseTrait) in a somewhat easy fashion? Is there a better model for this which I'm missing?
Update
As per Tim's answer making the controllers implicit solves the problem, however if you want to have a class where you define your controllers + have 'func' on it's interface the compiler no longer seems to properly resolve the implicits. So if I try to do something like this
class ProcessorContainer {
implicit val fooProcessor = new FooProcessor(new FooModel)
implicit val barProcessor = new BarProcessor(new BarModel)
def func[T <: BaseTrait](p: T) = typedFunc(p)
private def typedFunc[T <: BaseTrait](p: T)(implicit processor: BaseProcessor[T]) =
processor.process(p)
}
class Test {
val processorContainer = new ProcessorContainer
processorContainer.func(Foo())
processorContainer.func(Bar())
}
I get the following compile error (one for Foo and one for Bar):
could not find implicit value for parameter processor: BaseProcessor[Foo]
not enough arguments for method
Is there a way around this? I could of course expose the controllers so they can be passed in implicitly, however I'd prefer not doing that.
You can create a simple typeclass by making the processors implicit and passing them as an extra argument to func:
implicit val fooProcessor = new FooProcessor(new FooModel)
implicit val barProcessor = new BarProcessor(new BarModel)
def func[T <: BaseTrait](p: T)(implicit processor: BaseProcessor[T]) =
processor.process(p)
If you pass a Foo to func it will call FooProcessor.process on it, and if you pass a Bar to func it will call BarProcessor on it.
Ideally I'd like to be able to do the following in Scala:
import Builders._
val myBuilder = builder[TypeToBuild] // Returns instance of TypeToBuildBuilder
val obj = myBuilder.methodOnTypeToBuildBuilder(...).build()
In principle the goal is simply to be able to 'map' TypeToBuild to TypeToBuildBuilder using external mapping definitions (i.e. assume no ability to change these classes) and leverage this in type inferencing.
I got the following working with AnyRef types:
import Builders._
val myBuilder = builder(TypeToBuild)
myBuilder.methodOnTypeToBuildBuilder(...).build()
object Builders {
implicit val typeToBuildBuilderFactory =
new BuilderFactory[TypeToBuild.type, TypeToBuildBuilder]
def builder[T, B](typ: T)(implicit ev: BuilderFactory[T, B]): B = ev.create
}
class BuilderFactory[T, B: ClassTag] {
def create: B = classTag[B].runtimeClass.newInstance().asInstanceOf[B]
}
Note that the type is passed as a function argument rather than a type argument.
I'd be supremely happy just to find out how to get the above working with Any types, rather than just AnyRef types. It seems this limitation comes since Singleton types are only supported for AnyRefs (i.e. my use of TypeToBuild.type).
That being said, an answer that solves the original 'ideal' scenario (using a type argument instead of a function argument) would be fantastic!
EDIT
A possible solution that requires classOf[_] (would really love not needing to use classOf!):
import Builders._
val myBuilder = builder(classOf[TypeToBuild])
myBuilder.methodOnTypeToBuildBuilder(...).build()
object Builders {
implicit val typeToBuildBuilderFactory =
new BuilderFactory[classOf[TypeToBuild], TypeToBuildBuilder]
def builder[T, B](typ: T)(implicit ev: BuilderFactory[T, B]): B = ev.create
}
class BuilderFactory[T, B: ClassTag] {
def create: B = classTag[B].runtimeClass.newInstance().asInstanceOf[B]
}
Being able to just use builder(TypeToBuild) is really just a win in elegance/brevity. Being able to use builder[TypeToBuild] would be cool as perhaps this could one day work (with type inference advancements in Scala):
val obj: TypeToBuild = builder.methodOnTypeToBuildBuilder(...).build();
Here is a complete, working example using classOf: http://ideone.com/94rat3
Yes, Scala supports return types based on the parameters types. An example of this would be methods in the collections API like map that use the CanBuildFrom typeclass to return the desired type.
I'm not sure what you are trying to do with your example code, but maybe you want something like:
trait Builder[-A, +B] {
def create(x: A): B
}
object Builders {
implicit val int2StringBuilder = new Builder[Int, String] {
def create(x: Int) = "a" * x
}
def buildFrom[A, B](x: A)(implicit ev: Builder[A, B]): B = ev.create(x)
}
import Builders._
buildFrom(5)
The magic with newInstance only works for concrete classes that have a constructor that takes no parameters, so it probably isn't generic enough to be useful.
If you're not afraid of implicit conversions, you could do something like this:
import scala.language.implicitConversions
trait BuilderMapping[TypeToBuild, BuilderType] {
def create: BuilderType
}
case class BuilderSpec[TypeToBuild]()
def builder[TypeToBuild] = BuilderSpec[TypeToBuild]
implicit def builderSpecToBuilder[TypeToBuild, BuilderType]
(spec: BuilderSpec[TypeToBuild])
(implicit ev: BuilderMapping[TypeToBuild, BuilderType]) = ev.create
case class Foo(count: Int)
case class FooBuilder() {
def translate(f: Foo) = "a" * f.count
}
implicit val FooToFooBuilder = new BuilderMapping[Foo, FooBuilder] {
def create = FooBuilder()
}
val b = builder[Foo]
println(b.translate(Foo(3)))
The implicit conversions aren't too bad, since they're constrained to these builder-oriented types. The conversion is needed to make b.translate valid.
It looked like wingedsubmariner's answer was most of what you wanted, but you didn't want to specify both TypeToBuild and BuilderType (and you didn't necessarily want to pass a value). To achieve that, we needed to break up that single generic signature into two parts, which is why the BuilderSpec type exists.
It might also be possible to use something like partial generic application (see the answers to a question that I asked earlier), though I can't put the pieces together in my head at the moment.
I'll resort to answering my own question since a Redditor ended up giving me the answer I was looking for and they appear to have chosen not to respond here.
trait Buildable[T] {
type Result
def newBuilder: Result
}
object Buildable {
implicit object ABuildable extends Buildable[A] {
type Result = ABuilder
override def newBuilder = new ABuilder
}
implicit object BBuildable extends Buildable[B] {
type Result = BBuilder
override def newBuilder = new BBuilder
}
}
def builder[T](implicit B: Buildable[T]): B.Result = B.newBuilder
class ABuilder {
def method1() = println("Call from ABuilder")
}
class BBuilder {
def method2() = println("Call from BBuilder")
}
Then you will get:
scala> builder[A].method1()
Call from ABuilder
scala> builder[B].method2()
Call from BBuilder
You can see the reddit post here: http://www.reddit.com/r/scala/comments/2542x8/is_it_possible_to_define_a_function_return_type/
And a full working version here: http://ideone.com/oPI7Az
There are some cases in Scala when I need to use a cast, although I would say it is not strictly required. Consider the following program:
abstract class A {
type T <: F[T]
}
abstract class F[T <: F[T]] {
def me: String
}
class B extends A {
type T = TB
}
class TB extends F[TB] {
def me = "It's me"
def you = "It's you"
}
trait Operator[S <: A] extends Function[S#T,String]
object f1 extends Operator[A] {
def apply(x: A#T) = x.me
}
object f2 extends Operator[B] {
def apply(x: B#T) = x.you
}
object Driver {
def main(args: Array[String]) {
val bi = new TB()
println(f1(bi.asInstanceOf[A#T]))
println(f2(bi))
}
}
If I remove asInstanceOf[A#T] in the main method the code does not compile. However, I do not think the cast is really necessary. Actually, looking at the generated bytecode with javap, there is no occurrence of the checkcast instruction. Is this a limit of the Scala type-checker or there is something I am missing?
This is a limit of the type-checker, but it's a reasonable one. Consider what you're asking it to prove to show that TB <: A#T: that there's some subclass of A (let's call it C) for which TB <: C#T and C#T is concrete. Such a subclass exists (i.e., B), but would we necessarily want the compiler to search A's entire hierarchy to find it?
The specification is unsound; see https://issues.scala-lang.org/browse/SI-7278 among others.
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.