I would like the following code to compile, after making forgetBA implicit again.
trait ImplicitExample {
trait AA[T]
trait AB[T] extends AA[T]
trait BA[T] extends AA[T]
trait BB[T] extends AB[T] with BA[T]
object AA {
implicit def forgetAB[T: AB]: AA[T] = implicitly[AA[T]]
/*implicit*/ def forgetBA[T: BA]: AA[T] = implicitly[AA[T]]
}
object AB {
implicit def forgetBB[T: BB]: AB[T] = implicitly[AB[T]]
}
object BA {
implicit def forgetBB[T: BB]: BA[T] = implicitly[BA[T]]
}
object BB {
implicit object BBInt extends BB[Int]
}
val AAInt = implicitly[AA[Int]]
}
I understand that this will result in an ambiguous implicit resolution problem, so I'm looking for a way to indicate a preference for one implicit resolution over the other.
I've heard rumours that inserting intermediate traits in some way might help, but I can't seem to find an explanation.
The usual trick is to write something like this:
trait LowPriorityAAInstances {
implicit def forgetAB[T: AB]: AA[T] = implicitly[AA[T]]
}
object AA extends LowPriorityAAInstances {
implicit def forgetBA[T: BA]: AA[T] = implicitly[AA[T]]
}
This will give forgetBA priority when looking for an instance of AA for a T for which there's an instance of BA (while still compiling even if there's an instance of AB around).
The naming is entirely a matter of convention, but it's a good idea to use it to indicate that you're only breaking up the definition of AA in this way to accommodate the implicit search mechanism.
Related
I am trying to get hold of a shapeless Generic for a case class with a marker trait, like this:
case class X(a:String)
trait UniversalTrait extends Any {}
object MyApp extends App {
val ok = Generic[X]
val notOk = Generic[X with UniversalTrait]
}
It doesn't compile, with error could not find implicit value for parameter gen: shapeless.Generic[X with UniversalTrait] in the notOk line. Why is that? And can something be done?
Side note: I thought that it might be something to do with from not being able to add the marker trait to the returned instance, so I attempted fixing things by adding this:
object UniversalTrait {
implicit def genGeneric[P1<:Product with UniversalTrait,P2<:Product,L<:HList]
(implicit constraint: P1 =:= P2 with UniversalTrait,
underlying: Generic.Aux[P2,L]): Generic.Aux[P1,L] = new Generic[P1]{
type Repr=L
def to(t: P1): Repr = underlying.to(t)
def from(r: Repr): P1 = underlying.from(r).asInstanceOf[P1]
}
}
However, the error remains.
Deriving works for algebraic data types only.
That is a (sealed) trait and case classes (objects) extending the trait.
case class X(a:String) extends UniversalTrait
sealed trait UniversalTrait extends Any {}
val ok = Generic[X]
If I have 1 trait and 2 objects:
trait MyClass {
type T <: MyClass
def foo(): ClassTag[T] = {...}
}
object ChildClass1 extends MyClass {
type T = String
}
object ChildClass2 extends MyClass {
type T = Option[String]
}
is it possible to implement foo() in MyClass, such that ChildClass1.foo() yields ClassTag[String], and ChildClass2.foo() yields ClassTag[Option].
If not, what's the easiest way to bypass it? It should be noted that the implementation of T may be inner classes/objects, so hacking reflection may have some side effects.
Ok, it's possible that I don't completely understand your goal, but from what I can see, you are trying to create a trait with an upper bound type, and you also want to be able to get the type at runtime, correct?
So let's assume you have a Foo trait:
class MyClass // not important
trait Foo[T <: MyClass] {
def foo: ClassTag[T]
}
If you want an object implementation, the solution is trivial, since you know the type at compile time:
class MyClassSubclass extends MyClass // also not important
object FooObject extends Foo[MyClassSubclass] {
def foo: ClassTag[MyClassSubclass] = ClassTag(classOf[MyClassSubclass])
}
But if you want a class, then you can solve the problem with the implicitly + context bound combo in a pretty readable way:
class FooImpl[T <: MyClass : ClassTag] extends Foo[T] {
def foo: ClassTag[T] = implicitly[ClassTag[T]]
}
I would like to propose a dirty and impaired answer, please advice me if you have any better idea:
lazy val mf: ClassTag[T] = {
val clazz = this.getClass
val name = clazz.getName
val modifiedName = name + "T"
val reprClazz = Utils.classForName(modifiedName)
Manifest.classType(reprClazz)
}
it only works if the subclass is a singleton object.
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.
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.
I'm trying to implement a Scala trait that handles the details of interfacing with a Java library that requires us to create
What I want to do is something like:
trait SomeTrait[A] extends JavaAPI {
def foo = {
callApi(classOf[A])
}
override def bar = {
foo
}
}
Note that bar is actually overriding a method from a base class, so I can't change it's signature.
I've tried several variations with Manifests, etc., but can't quite get this to work. Is there a way to get the runtime class of a parameterized type?
This flavour should do the trick:
trait SomeTrait[A] {
def foo(implicit ev: Manifest[A]) = {
callApi(ev.erasure)
}
}
update At some point, the manifest must be injected via a method parameter. A constructor would be a good choice, if traits could have them.
Actually, they can! The trait has the constructor of whatever it's mixed-in to, so if you specify an abstract manifest that deriving classes must define...
trait SomeTrait {
def ev: Manifest[_] //abstract
def foo = println(ev.erasure)
}
//this `ev` provides the implementation, note that it MUST be a val, or var
class Concrete[T](implicit val ev: Manifest[T]) extends SomeTrait
And all is good again.
You have to get the manifest in there somehow, and traits have no constructor parameters. Only you can say what tradeoff you want to make. Here's another one.
trait SomeTrait[A] {
implicit def manifesto: Manifest[A]
def foo = println(manifest[A].erasure)
}
object SomeTrait {
def apply[A: Manifest] : SomeTrait[A] = new SomeTrait[A] { def manifesto = manifest[A] }
}
Due to type erasure, the compiler has no way to figure out what the type should be within the trait. Thus what you want can't be done. However, you could make it a class. That way the compiler can pass an evidence parameter when an instance is created.
class SomeTrait[A](implicit ev: Manifest[A]) extends JavaApi {
def foo = {
callApi(ev.erasure)
}
override def bar = {
foo
}
}
It might be a little inconvenient to do so in your code, but you can do this
trait SomeTrait[A] extends JavaAPI {
def objType: Class[A]
def foo = {
callApi(objType)
}
override def bar = {
foo
}
}
object SomeImplementation with SomeTrait[SomeObject] {
val objType: Class[SomeObject] = classOf[SomeObject]
}
I know it is a little wordy, but that's the way I solved this problem. I hope to find a better solution in the future, but this is what I'm using now. Let me know if that helps you.