Why isn't this Scala implicit conversion working? - scala

Update: I've accepted an answer but I'm still very curious why what I tried doesn't work (to understand Scala implicit behaviors). Any other answers would be greatly appreciated.
(Hopefully this question is answerable without much knowledge of Circumflex, but just in case, here's the documented source code reference.)
I'm trying to add some convenience functions over the Circumflex ORM library, but I'm running into some barriers trying to use Scala implicit conversions. Below, why doesn't the implicit conversion trigger? I suspect there's some complex interaction with the subclassing and/or the recursive type parameters.
import ru.circumflex.orm._
// I subclass Record and Table to add my own convenience methods etc. (not pasted, irrelevant)
abstract class XRecord[PK, R <: XRecord[PK, R]] extends Record[PK, R] { this: R => }
trait XTable[PK, R <: XRecord[PK, R]] extends Table[PK, R] { this: R => }
// Example entity.
class Org extends XRecord[Long,Org] {
val id = "id".BIGINT.NOT_NULL.AUTO_INCREMENT
def PRIMARY_KEY = id
def relation = Org
}
object Org extends Org with XTable[Long,Org]
object Test extends App {
// I want this conversion to work for all Records, not just XRecords.
// Need implicit f to be able to accept XRecord, a subclass of Record.
implicit def toRichRelationNode[PK, R <: Record[PK,R], RR](xs: RR)(implicit f: RR => RelationNode[PK,R]) =
new { def GET(f: RelationNode[PK,R] => Predicate) = 0 }
// This works.
toRichRelationNode(Org) GET (_.id EQ 1)
// This doesn't:
// "No implicit view available from Org.type => ru.circumflex.orm.RelationNode[PK,R]."
Org GET (_.id EQ 1)
}

Frankly, I've never used implicit parameters and I've never met a condition which forced me to use them (Circumflex itself is written without implicit parameters and goes pretty well as far as I am concerned).
Anyhow, I've been able to reproduce your scenario and make it work. It took 2 implicits, however, to make everything go fine. Here's the code:
// The helper which holds custom methods, it will accept any subclass of R
class NodeHelper[PK, R <: Record[PK, R]](val node: RelationNode[PK, R]) {
def GET(f: R => Predicate): Option[R] = node.criteria.add(f(node)).unique()
}
// Now the implicits and usage scenario
object Tester {
implicit def nodeToHelper[PK, R <: Record[PK, R]](node: RelationNode[PK, R]): NodeHelper[PK, R] = new NodeHelper(node)
implicit def tableToHelper[PK, R <: Record[PK, R]](table: Table[PK, R]): NodeHelper[PK, R] = new NodeHelper(table.AS("this"))
// Testing with table
println(User GET (_.cn EQ "patrick"))
// Testing with node
println(User.AS("u") GET (_.cn EQ "patrick"))
}
// And finally, the test model we've mentioned above
class User extends Record[Long, User] {
def PRIMARY_KEY = id
val id = "id".BIGINT.NOT_NULL.AUTO_INCREMENT
val cn = "cn".TEXT.NOT_NULL
def relation = User
}
object User extends User with Table[Long, User]
Hope it helps.

Related

Using dependent type to generate compile error

Use case: Writing a generic function like
def tenantFilterQuery[T, Q <: Table[T]](t: Q, e: TableQuery[Q], id: Int)(implicit s: Session) :Query[Q,Q#TableElementType,Seq] = {
e.filter(_.tenantId === id)
}
I am trying to add compile time intelligence that e.filter(_.tenantId === id) filter should ONLY be applied if for passed T there exists a property named tenantId else it'll not apply that filter if T didn't have that property.
Can this be worked out with dependent path types with or without using shapeless?
As a second step trying to come up with a way where when final Query is made and if T has property named tenantId it'll fail at compile time if it didn't have filter on tenantId. Think I should create a separate question for this one once first one is figured out.
The second question is the easier one: you can just use a structural type, T <: {def tenantId: Int}, and then it's only possible to call this with such a T.
If you want the filter to happen for those types and not happen for another type, I guess you could do that by providing an implicit helper? Something like:
sealed trait Helper[T]{
def applyToQuery[Q <: Table[T]](e: TableQuery[Q]): TableQuery[Q]
}
trait LowPriorityHelper {
implicit def withoutTenantId[T] = new Helper[T] {
def applyToQuery[Q <: Table[T]](e: TableQuery[Q]): TableQuery[Q] = e
}
}
object Helper extends LowPriorityHelper {
implicit def withTenantId[T <: {def tenantId: Int}] =
new Helper[T] {
def applyToQuery[Q <: Table[T]](e: TableQuery[Q]): TableQuery[Q] =
e.filter(_.tenantId === id)
}
}
def doQuery[T: Helper] = { val e = ...; implicitly[Helper[T]].applyToQuery(e)...}
The withTenantId Helper will be passed for T that has a tenantId, and the withoutTenantId one otherwise.

Is it possible to define a function return type based on a defined mapping from the type of a function argument?

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

Scala implicit conversion on generic trait implementing Java interface

I have been working on an issue with implicit conversion for days now, but somehow I just cannot figure out what I am doing wrong. I read through all the other questions on SO that deal with implicits but I still don't understand what the problem is.
As an example, let's consider a Java interface like this(T extends Object for brevity):
public interface JPersistable<T extends Object> {
public T persist(T entity);
}
In scala, I do the following:
case class A()
case class B() extends A
case class C()
case class D() extends C
trait Persistable[DTOType <: A, EntityType <: C] {
// this would be implemented somewhere else
private def doPersist(source: EntityType): EntityType = source
// this does not implement the method from the Java interface
private def realPersist(source: DTOType)(implicit view: DTOType => EntityType): EntityType = doPersist(source)
// this DOES implement the method from the Java interface, however it throws:
// error: No implicit view available from DTOType => EntityType.
def persist(source: DTOType): EntityType = realPersist(source)
}
case class Persister() extends Persistable[B, D] with JPersistable[B]
object Mappings {
implicit def BToD(source: B): D = D()
}
object Test {
def main(args: Array[String]) {
import Mappings._
val persisted = Persister().persist(B())
}
}
As stated in the comment, I get an exception at compile time. I guess my questions are:
1) Why do I need to specify the implicit conversion on the doRealPersist explicitly? I expected the conversion to happen even if I do the following:
trait Persistable[DTOType <: A, EntityType <: C] {
// this would be implemented somewhere else
private def doPersist(source: EntityType): EntityType = source
def persist(source: DTOType): EntityType = doPersist(source)
}
However, this does not compile either.
2) Why does compilation fail at persist and not at the actual method call (val persisted = Persister().persist(B()))? That should be the first place where the actual type of EntityType and DTOType are known, right?
3) Is there a better way to do what I am trying to achieve? Again, this is not the actual thing I am trying to do, but close enough.
Apologies in advance if this question is ignorant and thanks a lot in advance for your help.
You need to make the conversion available within the trait. You can't pass it in from the outside implicitly because the outside doesn't know that persist secretly requires realPersist which requires an implicit conversion. This all fails even without considering JPersistable.
You can for example add
implicit def view: DTOType => EntityType
as a method in the trait and it will then compile. (You can drop realPersist then also.)
Then you need a way to get that view set. You can
case class Persister()(implicit val view: B => D) extends Persistable[B,D]
and then you're all good. (The implicit val satisfies the implicit def of the trait.)
But now you have bigger problems: your Java interface signature doesn't match your Scala signature. The equivalent Scala is
trait JPersistable[T <: Object] { def persist(t: T): T }
See how persist takes and returns the same type? And see how it does not in your Scala class? That's not going to work, nor should it! So you have to rethink exactly what you're trying to accomplish here. Maybe you just want to make the implicit conversion available--not pass it to the method!--and have Scala apply the implicit conversion for you so that you think you've got a persist that maps from DTOType to EntityType, but you really just have the EntityType to EntityType transform that the Java interface requires.
Edit: for example, here's a working version of what you posted just using standard implicit conversion:
trait JPer[T] { def persist(t: T): T }
class A
case class B() extends A
class C
case class D() extends C
trait Per[Y <: C] extends JPer[Y] {
private def doIt(y: Y): Y = y
def persist(y: Y) = doIt(y)
}
case class Perer() extends Per[D] // "with JPer" wouldn't add anything!
object Maps { implicit def BtoD(b: B): D = D() }
object Test extends App {
import Maps._
val persisted = Perer().persist(B())
}
Pay attention to which types are used where! (Who takes B and who takes D and which direction do you need a conversion?)

Why these implicit conversions resulted in looping code

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.

Minimal framework in Scala for collections with inheriting return type

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.