I have the following trait and classes:
trait A{
def func1: String
def func2: Int
}
class F extends A{
def func1: String = ???
def func2: Int = ???
}
class G extends A{
def func1: String = ???
def func2: Int = ???
}
And I want to create the following trait and class:
trait X{
val a: ***
}
class Z extends X{
override val a = new G
}
What do I need to write on '***' in trait X so that I can assign val a with a class F or G ?
Thank you.
EDIT
Sorry, I forgot to mention that trait A is A[Any] and traits F and G can be 'F extends A[String]' and 'G extends A[Int]'. In other words, the classes can extends the trait A with different types of parameters.
Re. your edit, your code fails because trait A only takes type parameter of a fixed type. If you declare base class having a A[Any], you cannot override it with a A[Int] or A[String]. There are two ways to make your code works.
One is to make trait A type argument covariant, so that you can override with subclass of the type argument you declared in base class (note the + in trait A definition):
trait A[+T]
class F extends A[String]
class G extends A[Int]
trait X {
val a: A[Any]
}
class Z extends X {
val a = new G
}
See here: Sample
Another way to work is to declare a as a A[_] (_ means it takes any type as a parameter, which is different from Any):
trait A[T]
class F extends A[String]
class G extends A[Int]
trait X {
val a: A[_]
}
class Z extends X {
val a = new G
}
See here: Sample
Related
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)
}
}
if I have an ADT and a type class, is there a way for me to ensure at compile time that there is an instance of the type class for every subtype of the ADT?
Just to give an example - I'd really like this to not compile as there isn't an instance of A for Baz
sealed trait Foo
final case class Bar(s: String) extends Foo
final case class Baz(i: Int) extends Foo
trait A[T <: Foo] {
type O
def f(t: T): O
}
implicit val barA = new A[Bar] {
type O = String
def f(t: Bar): O = t.s
}
This is all my own code, so I'm happy to change the encoding of Foo if required (maybe a shapeless coproduct can help me out here?)
EDIT
Sorry, should have mentioned - I have a function a bit like this I'd like to implement (lets assume my instances are in an object I've imported and they are the only implementations in scope)
def g[T <: Foo](fs: List[T])(implicit a: A[T]): List[a.O] = fs.map(a.f(_))
From the comments below, it looks like I should also have said that the thing that calls g can do so with a List of any subclass of Foo (I have no control over that part other than to change g I guess). Here, I'm trying to ensure that if someone changes Foo later on, then there will be a compiler error letting the user know that they need to implement an appropriate A
You can use F-bounded polymorphism (aka Curiously Recurrent Template Pattern):
sealed abstract class Foo[Self <: Foo](implicit val hasA: A[Self])
final case class Bar(s: String) extends Foo[Bar]
final case class Baz(i: Int) extends Foo[Baz]
abstract class is used instead of trait so the implicit is picked up automatically.
However, for this specific A and g, you may not really need a type class:
sealed trait Foo[O] {
def f(): O
}
final case class Bar(s: String) extends Foo[String] {
def f() = s
}
def g(fs: List[Foo[O]]): List[O] = fs.map(_.f())
trait Foo[T] {
this: ImplementThis[T] =>
}
case class Bar() extends Foo[String] with ImplementThis[String] {
override def f(t: String): String = {
t
}
}
case class Baz() extends Foo[Int] with ImplementThis[Int] {
override def f(t: Int): Int = {
t
}
}
trait ImplementThis[T] {
type O
def f(t: T): O
}
Try something like this. This will enforce implementation of def f(t: T):O for any subclass of Foo that's defined.
def g[T <: Foo](fs: List[T])(implicit a: A[T]): List[a.O] = fs.map(a.f(_))
From this, I assume you want all the child classes of your Foo to have a def f so that they dont fail at runtime. I think my above suggestion will enforce that def f implementation and solve this problem.
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)
}
For example, I want to declare a trait to say in effect, "If class C implements this trait, it has a method m that returns an instance of class C".
All the ways I can think of just say that m returns an instance having that trait, which is not what I want at all.
You constrain the "self type" like so:
scala> trait Foo[Self] { self:Self => def m:Self }
defined trait Foo
scala> class A extends Foo[A] { def m = new A }
defined class A
scala> class B extends Foo[A] { def m = new B }
<console>:27: error: illegal inheritance;
self-type B does not conform to Foo[A]'s selftype Foo[A] with A
class B extends Foo[A] { def m = new B }
^
<console>:27: error: type mismatch;
found : B
required: A
class B extends Foo[A] { def m = new B }
^
scala> class B extends Foo[B] { def m = new A }
<console>:27: error: type mismatch;
found : A
required: B
class B extends Foo[B] { def m = new A }
If I understood your question correctly, you must be looking for something like this:
trait Foo[T] {
def m: T
}
class A extends Foo[A] {
def m = {
getInstanceOfAFromSomewhere()
}
}
class B extends Foo[B] {
def m = {
getInstanceOfBFromSomewhere()
}
}
Testing:
object Test extends App {
val a: Foo[_] = new A
println(a.m)
val b: Foo[_] = new B
println(b.m)
}
Output:
A#3d246f44
B#14a1373f
Hope this is what you are looking for
I would like to have a sealed trait which have a declared method that returns the
actual class that extends the trait. Should I use an abstract type, a parameter type or
is there any other nice way to solve this?
sealed trait Foo {
type T
def doit(other: T): T
}
or
sealed trait Foo[T] {
def doit(other: T): T
}
Note that T must be a subtype of Foo in this example. If I do it like this the type
information feels too repeated:
case class Bar(name: String) extends Foo[Bar] {
def doit(other: Bar): Bar = ...
}
They are mostly interchangeable. According to Odersky, the reason was mainly for completeness: That similarly to the fact that methods and fields (values) can be either abstract or passed as parameters, so can types.
It is better to use an abstract type when you intend to mix several traits that all use the same type name. With type parameters you need to explicitly pass the type to each
Here's an article explaining all of this: http://www.artima.com/weblogs/viewpost.jsp?thread=270195
You can cut down on the repetition somewhat by having your doit method return a factory function:
trait Foo[T] {
self: T =>
def doit: T => T
}
case class Bar(name: String) extends Foo[Bar] {
// note: types omitted
def doit = { other => Bar(name + other.name) }
}
It's not possible to do the same with an abstract type:
trait Foo {
self: T => // won't compile because T isn't defined yet
type T
def doit: T => T
}
You can write:
trait Foo[T] {
self:T =>
def doit(other: T): T
}
case class Bar(name: String) extends Foo[Bar] {
def doit(other: Bar): Bar = ...
}
The difference to your example is that Bar can't be instantiated in any other way (e.g. case class Bar(name: String) extends Foo[String]).
trait Foo[A <: Foo[A]]
This trait can only be mixed in if A is a subtype of Foo[A] and the only type satisfying that is the class Foo is being mixed into. I saw this solution in the Mapper traits in Lift.
EDIT - Below is my original answer. Your comment indicates that you wish to return an arbitrary instance of a matching type but I don't really believe that this is in any way sensible. Suppose it were, via the T.type syntax:
trait T { def foo : T.type }
trait U extends T { def foo = new U } //must be a U
class W extends U
val w : W = (new W).foo //oh dear.
This is accomplishable via this.type:
scala> trait T {
| def foo : this.type
| }
defined trait T
scala> class W extends T {
| def foo = this
| }
defined class W
scala> (new W).foo
res0: W = W#22652552
scala> res0.foo
res1: res0.type = W#22652552
And then also:
scala> ((new W) : T)
res4: T = W#45ea414e
scala> res4.foo.foo.foo
res5: res4.type = W#45ea414e