I need overriding implicit in object res defing one from trait. The purpose is to define custom implicits in one place (trait B). Trait a is defined in external library. Is it possible?
trait t {
}
object m extends t
object q extends t
trait a {
implicit val o: t = m
}
trait b {
implicit val o: t = q
}
trait c {
def action(implicit v: t): Unit = {}
}
object res extends c with a with b {
//i need smth like override val o = super[b].o
val ololo= action
}
It is not possible to mix-in two unrelated traits that both contain a member with the same identifier. The Scala compiler has no way to resolve which one would take precedence in this scenario. Since types A and B are related, o does not even need to have the same type in both of them. Trait B needs to extend A and override o. There isn't any other way to override a member without using inheritance.
trait T
case object M extends T
case object Q extends T
trait A {
implicit val o: T = M
}
trait B extends A {
override implicit val o: T = Q
}
trait C {
def action(implicit v: T): Unit = println(v)
}
object Res extends C with B {
def call() = action
}
scala> Res.call()
Q
Since you are already mixing A into Res anyway, it is assumed that A is not difficult to extend, since Res must implement any other unmentioned abstract members.
Related
In Scala 2.12, I can implement a nullary method with a case object:
trait T[X] {
def f: X
}
trait XImpl {
def sayHi: String
}
object O extends T[XImpl] {
case object f extends XImpl {
val sayHi = "Hi"
}
}
> defined trait T
> defined trait XImpl
> defined object O
But if I add a method with arguments, and implement it with a case class, it does not work:
trait T[X] {
def f: X
def g(x: X): X
}
trait XImpl {
def sayHi: String
}
object O extends T[XImpl] {
case object f extends XImpl {
val sayHi = "Hi"
}
case class g(x: XImpl) extends XImpl {
def sayHi = x.sayHi.toUpperCase
}
}
> error: object creation impossible, since method g in trait T of type (x: XImpl)XImpl is not defined
Is there some magic to make it work, or do I have to implement a method that simply instantiates the case class ?
An object behaves like a (lazy) val, and that's why it can be used to implement a nullary def.
A case class is a combination of a class and an object (and so a lazy val), but neither of them can implement a def with parameters.
This also means that making your class implicit instead of case works, because then it defines an implicit def with that name as well. But I wouldn't recommend it to solve this problem.
do I have to implement a method that simply instantiates the case class
Yes. Note that to avoid accidental recursion it needs to be
def g(x: XImpl) = new g(x) // or g.apply(x), but not g(x)
The thing is that case class are not instances.
But to satisfy your trait T, you need to ensure that O implementing T[XImpl] has a property named g which confirms to type XImpl. And surely your case class g does not.
And if you are thinking about the companion object of g, then it conforms to the anonymous type g.type and will not confirm to XImpl.
Basicaly this is what I am trying to do.
A trait that has a member and another trait that inherits that member and initialize it.
Then a class that takes a generic type that must be inherited from the first trait and accesses that member
object main extends App{
val z = new c[b]()
z.p()
}
trait a{
val x : String
}
trait b extends a {
val x = 1
}
class c [A <: a] {
self: A =>
def p(): Unit ={
print(x)
}
}
but in the line
val z = new c[b]()
c[b] is underlined and the compiler complains that
"Illegal inheritance, self-type c[b] does not conform to A"
I want to define multiple traits that inherit from a father trait and then define a class that takes one of the fathers child traits and accesses its values
I found the answer, I simply had to extend the object while creating it, like this:
object main extends App{
val z = new c[b] with b
z.p()
}
trait a{
val x : String
}
trait b extends a {
val x = "1"
}
class c[A <: a]{
this: A =>
def p(): Unit ={
print(x)
}
}
I'm currently working on a A* implementation in Scala. To accomplish a clean structure I would like to use a nested case class structure which implements a self-bounded trait. However, I experience some issues when implementing this in the Scala IDE. The following code will not compile:
trait A[T <: A[T]]
class B {
case class C(int: Int) extends A[C] // A[this.C] won't work either
def make = C(5)
}
object D {
def foo[T <: A[T]](some: T) = {}
val c = new B().make
foo(c) // this does not compile
}
Is there any way I can make this structure work?
Not sure why you want this, but here's why it won't work as is:
The type of D.c is B#C. It is a path-dependent type where we don't know what instance of B it belongs to. However, C extends A[C], which is the already the same as saying A[this.C] in that context, which is bound to a specific instance of B. foo sees the type parameter T as B#C, which is not the same as b.C for some b.
You have two options to make this compile.
Relax the constraints of A to B#C:
trait A[T <: A[T]]
class B {
case class C(int: Int) extends A[B#C]
def make = C(5)
}
object D {
def foo[T <: A[T]](some: A[T]) = {}
val c = new B().make
foo(c)
}
Or handle the path-dependent type, so that c has type b.C:
trait A[T <: A[T]]
class B {
case class C(int: Int) extends A[C]
def make = C(5)
}
object D {
def foo[T <: A[T]](some: A[T]) = {}
val b = new B
val c: b.C = b.make
foo(c)
}
I'm very new to Scala programming, and I really like the degree to which code is composable. I wanted to write some traits that deal with two related objects that are convertible to each other, and build more functionality by continuing to extend that trait so that when I create objects I can specify the related types for my generics. Here is a working toy example of the type of code I'm talking about:
trait FirstConverter[First] {
def toFirst: First
}
trait SecondConverter[Second] {
def toSecond: Second
}
trait TwoWayConverter[First <: SecondConverter[Second], Second <: FirstConverter[First]] {
def firstToSecond(x: First) = x.toSecond
def secondToFirst(x: Second) = x.toFirst
}
trait RoundTripConverter[First <: SecondConverter[Second], Second <: FirstConverter[First]] extends TwoWayConverter[First, Second] {
def firstToFirst(x: First) = secondToFirst(firstToSecond(x))
def secondToSecond(x: Second) = firstToSecond(secondToFirst(x))
}
case class A(s: String) extends SecondConverter[B] {
def toSecond: B = B((s.toInt) + 1)
}
case class B(i: Int) extends FirstConverter[A] {
def toFirst: A = A((i * 2).toString)
}
object ABConverter extends RoundTripConverter[A, B]
object Main {
def main(args: Array[String]): Unit = {
println(ABConverter firstToSecond A("10")) // 11
println(ABConverter secondToFirst B(42)) // 84
println(ABConverter firstToFirst A("1")) // 4
println(ABConverter secondToSecond B(2)) // 5
}
}
While this works, I'm not sure if it's idiomatic Scala. I'm asking if there are any tricks to make the type definitions more concise and if I can somehow define the type restrictions only once and have them used by multiple traits which extend other traits.
Thanks in advance!
One way to improve your design would be to use a type class instead of inheriting from FirstConverter and SecondConverter. That way you could use multiple conversion functions for the same types and convert between classes you don't control yourself.
One way would be to create a type class which can convert an A into a B :
trait Converter[A, B] {
def convert(a: A): B
}
trait TwoWayConverter[A, B] {
def firstToSecond(a: A)(implicit conv: Converter[A, B]): B = conv.convert(a)
def secondToFirst(b: B)(implicit conv: Converter[B, A]): A = conv.convert(b)
}
trait RoundTripConverter[A, B] extends TwoWayConverter[A, B] {
def firstToFirst(a: A)(implicit convAB: Converter[A, B], convBA: Converter[B, A]) =
secondToFirst(firstToSecond(a))
def secondToSecond(b: B)(implicit convAB: Converter[A, B], convBA: Converter[B, A]) =
firstToSecond(secondToFirst(b))
}
We could create type class instances for the following two classes Foo and Bar similar to your A and B
case class Foo(s: String)
case class Bar(i: Int)
implicit val convFooBarFoor = new Converter[Foo, Bar] {
def convert(foo: Foo) = Bar((foo.s toInt) + 1)
}
implicit val convBarFoo = new Converter[Bar, Foo] {
def convert(bar: Bar) = Foo((bar.i * 2) toString)
}
We then could create a FooBarConverter :
object FooBarConverter extends RoundTripConverter[Foo, Bar]
FooBarConverter firstToSecond Foo("10") // Bar(11)
FooBarConverter secondToFirst Bar(42) // Foo(84)
FooBarConverter firstToFirst Foo("1") // Foo(4)
FooBarConverter secondToSecond Bar(2) // Bar(5)
The only problem is because we can not pass parameters to a trait, we can not limit the types to types with a Converter type class instance. So you can create the StringIntConverter below even if no Converter[String, Int] and/or Convert[Int, String] instances exist.
object StringIntConverter extends TwoWayConverter[String, Int]
You cannot call StringIntConverter.firstToSecond("a") because the firstToSecond method needs the implicit evidence of the two mentioned type class instances.
Assuming the following setup:
trait A[L] { def op(l1:L, l2:L): L }
trait E[L] { def op(l:L): L }
implicit def some2E[L:A](self:L) = new E[L] { def op(other:L) =
implicitly[A[L]].op(self,other) }
Is there a way to directly expand m op n to a.op(m,n), in a context where a is the appropriate implicit A, using macros or at least avoid the additional object creation?
If you move the implicit parameter to the op method, you can use a value class to prevent the additional object creation:
implicit class some2E[L](val self: L) extends AnyVal {
def op(other: L)(implicit x: A[L]) = x.op(self, other)
}
Hotspot will probably inline the call to theop defined in some2E, so you will end up with a.op(m, n).