- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Re: Extending the same trait with two different generic parameters
Thu, 2012-01-12, 19:22
Yes I realized that just after writing the email... so what is the best pattern to do that???
trait FooString extends Foo[String]trait FooInt extends Foo[Int]
class Twice extends FooString with FooInt ?
Best Regards
2012/1/12 Matthew Pocock <turingatemyhamster@gmail.com>
trait FooString extends Foo[String]trait FooInt extends Foo[Int]
class Twice extends FooString with FooInt ?
Best Regards
2012/1/12 Matthew Pocock <turingatemyhamster@gmail.com>
Hi Edmondo,
This isn't possible. The JVM/bytecode representation of classes erases the type of generic parameters, so it wouldn't be able to tell Foo[String] from Foo[Int] appart in your implementation.
trait Foo[T] { def foo(t: T)}
class Twice extends Foo[String] with Foo[Int] // no good, as Foo[String] and Foo[Int] become Foo[_]
The way I achieve this kind of thing is to use type classes and implicits.
class Twice
trait Foo[T] { def foo(t: T): Unit}
object Foo { implicit stringFoo: Foo[String] = new Foo[String] { def foo(s: String): Unit = println("Got string " + s) } implicit intFoo: Foo[Int] = new Foo[Int] { def foo(i: Int): Unit = println("Got int " + i) }}
def twiceHandler[T](twice: Twice, t: T)(implicitly tFoo: Foo[T]): Unit = { println("In twice handler") tFoo.foo(t)}
Matthew
On 12 January 2012 18:07, Edmondo Porcu <edmondo.porcu@gmail.com> wrote:
Dear All,
I would like to write a class who extend the same trait twice, with a different generic parameter.
This is not possible, what is the best way to achieve that?
Best Regards
Edmondo
--
Dr Matthew PocockIntegrative Bioinformatics Group, School of Computing Science, Newcastle University mailto: turingatemyhamster@gmail.com gchat: turingatemyhamster@gmail.commsn: matthew_pocock@yahoo.co.uk irc.freenode.net: drdozerskype: matthew.pococktel: (0191) 2566550mob: +447535664143
Thu, 2012-01-12, 20:31
#2
Re: Extending the same trait with two different generic paramet
c# can do this:
class FooX : Foo<string>, Foo<Int> { public int Foo<int>.bar() { return 42; } public string Foo<string>.bar() { return "xyz"; }}
On Friday, January 13, 2012 2:22:15 AM UTC+8, edmondo1984 wrote:
class FooX : Foo<string>, Foo<Int> { public int Foo<int>.bar() { return 42; } public string Foo<string>.bar() { return "xyz"; }}
On Friday, January 13, 2012 2:22:15 AM UTC+8, edmondo1984 wrote:
Yes I realized that just after writing the email... so what is the best pattern to do that???
trait FooString extends Foo[String]trait FooInt extends Foo[Int]
class Twice extends FooString with FooInt ?
Best Regards
2012/1/12 Matthew Pocock <turingate...@gmail.com>Hi Edmondo,
This isn't possible. The JVM/bytecode representation of classes erases the type of generic parameters, so it wouldn't be able to tell Foo[String] from Foo[Int] appart in your implementation.
trait Foo[T] { def foo(t: T)}
class Twice extends Foo[String] with Foo[Int] // no good, as Foo[String] and Foo[Int] become Foo[_]
The way I achieve this kind of thing is to use type classes and implicits.
class Twice
trait Foo[T] { def foo(t: T): Unit}
object Foo { implicit stringFoo: Foo[String] = new Foo[String] { def foo(s: String): Unit = println("Got string " + s) } implicit intFoo: Foo[Int] = new Foo[Int] { def foo(i: Int): Unit = println("Got int " + i) }}
def twiceHandler[T](twice: Twice, t: T)(implicitly tFoo: Foo[T]): Unit = { println("In twice handler") tFoo.foo(t)}
Matthew
On 12 January 2012 18:07, Edmondo Porcu <edmond...@gmail.com> wrote:
Dear All,
I would like to write a class who extend the same trait twice, with a different generic parameter.
This is not possible, what is the best way to achieve that?
Best Regards
Edmondo
--
Dr Matthew PocockIntegrative Bioinformatics Group, School of Computing Science, Newcastle University mailto: turingate...@gmail.com gchat: turingate...@gmail.commsn: matthew...@yahoo.co.uk irc.freenode.net: drdozerskype: matthew.pococktel: (0191) 2566550mob: +447535664143
Thu, 2012-01-12, 20:41
#3
Re: Extending the same trait with two different generic paramet
If you are set on it, you can use views to map Twice => Foo[Int] and Twice => Foo[String].
scala> trait Foo[T] { | def bar: T | }defined trait Foo
scala> case class Twice(name: String, age: Int)defined class Twice
scala> case class TwiceFooInt(t: Twice) extends Foo[Int] { | def bar = t.age | }defined class TwiceFooInt
scala> case class TwiceFooString(t: Twice) extends Foo[String] { | def bar = t.name | } defined class TwiceFooString
scala> implicit def twice2fooInt(t: Twice) = TwiceFooInt(t)twice2fooInt: (t: Twice)TwiceFooInt
scala> implicit def twice2fooString(t: Twice) = TwiceFooString(t) twice2fooString: (t: Twice)TwiceFooString
scala> val a = Twice("Bob", 88)a: Twice = Twice(Bob,88)
scala> def age(foo: Foo[Int]): Int = foo.bar age: (foo: Foo[Int])Int
scala> age(a)res0: Int = 88
scala> def name(foo: Foo[String]): String = foo.barname: (foo: Foo[String])String
scala> name(a)res1: String = Bob
There will be problems if you, for example,
scala> a.bar<console>:18: error: type mismatch; found : a.type (with underlying type Twice) required: ?{val bar: ?}Note that implicit conversions are not applicable because they are ambiguous: both method twice2fooInt in object $iw of type (t: Twice)TwiceFooInt and method twice2fooString in object $iw of type (t: Twice)TwiceFooString are possible conversion functions from a.type to ?{val bar: ?} a.bar
On Thu, Jan 12, 2012 at 1:37 PM, Sciss <contact@sciss.de> wrote:
scala> trait Foo[T] { | def bar: T | }defined trait Foo
scala> case class Twice(name: String, age: Int)defined class Twice
scala> case class TwiceFooInt(t: Twice) extends Foo[Int] { | def bar = t.age | }defined class TwiceFooInt
scala> case class TwiceFooString(t: Twice) extends Foo[String] { | def bar = t.name | } defined class TwiceFooString
scala> implicit def twice2fooInt(t: Twice) = TwiceFooInt(t)twice2fooInt: (t: Twice)TwiceFooInt
scala> implicit def twice2fooString(t: Twice) = TwiceFooString(t) twice2fooString: (t: Twice)TwiceFooString
scala> val a = Twice("Bob", 88)a: Twice = Twice(Bob,88)
scala> def age(foo: Foo[Int]): Int = foo.bar age: (foo: Foo[Int])Int
scala> age(a)res0: Int = 88
scala> def name(foo: Foo[String]): String = foo.barname: (foo: Foo[String])String
scala> name(a)res1: String = Bob
There will be problems if you, for example,
scala> a.bar<console>:18: error: type mismatch; found : a.type (with underlying type Twice) required: ?{val bar: ?}Note that implicit conversions are not applicable because they are ambiguous: both method twice2fooInt in object $iw of type (t: Twice)TwiceFooInt and method twice2fooString in object $iw of type (t: Twice)TwiceFooString are possible conversion functions from a.type to ?{val bar: ?} a.bar
On Thu, Jan 12, 2012 at 1:37 PM, Sciss <contact@sciss.de> wrote:
the problem arises as you use T in any method
trait Foo[T] { def lala: T }
what would Twice return? the only possible solution would be that T is the common supertype of Int and String, then Twice would be a Foo[Any] and could faithfully return either a String or an Int from `lala`.
i ran into this problem before, too, but when you carefully think about it, the idea of inheriting a trait twice with different type arguments is flawed.
so what is it exactly that you try to achieve with Twice?
best, -sciss-
On 12 Jan 2012, at 18:22, Edmondo Porcu wrote:
> Yes I realized that just after writing the email... so what is the best pattern to do that???
>
> trait FooString extends Foo[String]
> trait FooInt extends Foo[Int]
>
> class Twice extends FooString with FooInt ?
>
> Best Regards
>
> 2012/1/12 Matthew Pocock <turingatemyhamster@gmail.com>
> Hi Edmondo,
>
> This isn't possible. The JVM/bytecode representation of classes erases the type of generic parameters, so it wouldn't be able to tell Foo[String] from Foo[Int] appart in your implementation.
>
> trait Foo[T] {
> def foo(t: T)
> }
>
> class Twice extends Foo[String] with Foo[Int] // no good, as Foo[String] and Foo[Int] become Foo[_]
>
> The way I achieve this kind of thing is to use type classes and implicits.
>
> class Twice
>
> trait Foo[T] {
> def foo(t: T): Unit
> }
>
> object Foo {
> implicit stringFoo: Foo[String] = new Foo[String] {
> def foo(s: String): Unit = println("Got string " + s)
> }
>
> implicit intFoo: Foo[Int] = new Foo[Int] {
> def foo(i: Int): Unit = println("Got int " + i)
> }
> }
>
>
> def twiceHandler[T](twice: Twice, t: T)(implicitly tFoo: Foo[T]): Unit = {
> println("In twice handler")
> tFoo.foo(t)
> }
>
> Matthew
>
>
> On 12 January 2012 18:07, Edmondo Porcu <edmondo.porcu@gmail.com> wrote:
> Dear All,
>
> I would like to write a class who extend the same trait twice, with a different generic parameter.
>
> This is not possible, what is the best way to achieve that?
>
> Best Regards
>
> Edmondo
>
>
>
> --
> Dr Matthew Pocock
> Integrative Bioinformatics Group, School of Computing Science, Newcastle University
> mailto: turingatemyhamster@gmail.com
> gchat: turingatemyhamster@gmail.com
> msn: matthew_pocock@yahoo.co.uk
> irc.freenode.net: drdozer
> skype: matthew.pocock
> tel: (0191) 2566550
> mob: +447535664143
>
>
Thu, 2012-01-12, 20:51
#4
Re: Extending the same trait with two different generic paramet
sorry, i still don't understand what you want to do.
so `MyObj` == `T` and `T` is a sealed trait with three subtypes? Do items hold only one subtype of `T`, or a mix? and what is `apply` supposed to do?
maybe if you try to formulate _what_ exactly you want to do, in plain words, without the _how_, we can try to find out what is the best _how_?
best, -sciss-
On 12 Jan 2012, at 18:48, Edmondo Porcu wrote:
> Yes it is a design flaw, which I am not able to solve.
>
> The idea is the following:
>
> I have a special collections of item , let's say
>
> class MySpecialCollection(val items:IndexedSeq[MyObj]);
>
> this will support a given method for example apply (t:T) where T<:Something.
>
> However, this T-type depends on the items inside the collection, so I cannot determine it in advance...and since T can be only of three different subclasses.... I ended up doing something like that:
>
> class MySpecialCollectionForT1 {
>
> apply(t:T1) = do smth
> apply(t:T2) = throw new UnsupportedOperationException
> apply(t:T3) = throw new UnsupportedOperationException
>
> }
>
> This is a crappy design, but I couldn't imagine anything better... so If you could help me with that I would be very happy to change it :)
>
> Best Regards
>
>
>
> 2012/1/12 Sciss
> the problem arises as you use T in any method
>
> trait Foo[T] { def lala: T }
>
> what would Twice return? the only possible solution would be that T is the common supertype of Int and String, then Twice would be a Foo[Any] and could faithfully return either a String or an Int from `lala`.
>
> i ran into this problem before, too, but when you carefully think about it, the idea of inheriting a trait twice with different type arguments is flawed.
>
> so what is it exactly that you try to achieve with Twice?
>
> best, -sciss-
>
>
> On 12 Jan 2012, at 18:22, Edmondo Porcu wrote:
>
> > Yes I realized that just after writing the email... so what is the best pattern to do that???
> >
> > trait FooString extends Foo[String]
> > trait FooInt extends Foo[Int]
> >
> > class Twice extends FooString with FooInt ?
> >
> > Best Regards
> >
> > 2012/1/12 Matthew Pocock
> > Hi Edmondo,
> >
> > This isn't possible. The JVM/bytecode representation of classes erases the type of generic parameters, so it wouldn't be able to tell Foo[String] from Foo[Int] appart in your implementation.
> >
> > trait Foo[T] {
> > def foo(t: T)
> > }
> >
> > class Twice extends Foo[String] with Foo[Int] // no good, as Foo[String] and Foo[Int] become Foo[_]
> >
> > The way I achieve this kind of thing is to use type classes and implicits.
> >
> > class Twice
> >
> > trait Foo[T] {
> > def foo(t: T): Unit
> > }
> >
> > object Foo {
> > implicit stringFoo: Foo[String] = new Foo[String] {
> > def foo(s: String): Unit = println("Got string " + s)
> > }
> >
> > implicit intFoo: Foo[Int] = new Foo[Int] {
> > def foo(i: Int): Unit = println("Got int " + i)
> > }
> > }
> >
> >
> > def twiceHandler[T](twice: Twice, t: T)(implicitly tFoo: Foo[T]): Unit = {
> > println("In twice handler")
> > tFoo.foo(t)
> > }
> >
> > Matthew
> >
> >
> > On 12 January 2012 18:07, Edmondo Porcu wrote:
> > Dear All,
> >
> > I would like to write a class who extend the same trait twice, with a different generic parameter.
> >
> > This is not possible, what is the best way to achieve that?
> >
> > Best Regards
> >
> > Edmondo
> >
> >
> >
> > --
> > Dr Matthew Pocock
> > Integrative Bioinformatics Group, School of Computing Science, Newcastle University
> > mailto: turingatemyhamster@gmail.com
> > gchat: turingatemyhamster@gmail.com
> > msn: matthew_pocock@yahoo.co.uk
> > irc.freenode.net: drdozer
> > skype: matthew.pocock
> > tel: (0191) 2566550
> > mob: +447535664143
> >
> >
>
>
Thu, 2012-01-12, 21:01
#5
R: Re: Extending the same trait with two different generic para
Yes... You are right. Let's make an example:
There is a set of people... Each of them has a state: sad or happy.
A sad person can be guided for a city tour only by a SadGuide and a happy person can be guided only by an happy guide.
Let's say now you are a company, what would you like to do? Well... Make tours for group of people, because it's more efficient. So you create your collection of people, PeopleCollection.
If all the people are sad, you can guide all them only with a SadGuide, if they are all happy with a HappyGuide. If they differ, you can't create your PeopleCollection.
I am trying to achieve this behaviour... Now imagine to add another layer.
You have a office which groups the people , and you have to decide how many sad tours you have to organize and how many happy tours. You receive a collection of PeopleCollection from the other office, and you want to divide them. You try to collect and because of pattern matching, your collect doesn't work.
I got always stucked with erasure... In every possible implementation I imagined...
Thank you for your precious help
Edmondo
Inviato da BlackBerry(R) Wireless Handheld
-----Original Message-----
From: Sciss
Date: Thu, 12 Jan 2012 19:31:08
To: Edmondo Porcu; scala-user
Subject: Re: [scala-user] Extending the same trait with two different generic parameters
sorry, i still don't understand what you want to do.
so `MyObj` == `T` and `T` is a sealed trait with three subtypes? Do items hold only one subtype of `T`, or a mix? and what is `apply` supposed to do?
maybe if you try to formulate _what_ exactly you want to do, in plain words, without the _how_, we can try to find out what is the best _how_?
best, -sciss-
On 12 Jan 2012, at 18:48, Edmondo Porcu wrote:
> Yes it is a design flaw, which I am not able to solve.
>
> The idea is the following:
>
> I have a special collections of item , let's say
>
> class MySpecialCollection(val items:IndexedSeq[MyObj]);
>
> this will support a given method for example apply (t:T) where T<:Something.
>
> However, this T-type depends on the items inside the collection, so I cannot determine it in advance...and since T can be only of three different subclasses.... I ended up doing something like that:
>
> class MySpecialCollectionForT1 {
>
> apply(t:T1) = do smth
> apply(t:T2) = throw new UnsupportedOperationException
> apply(t:T3) = throw new UnsupportedOperationException
>
> }
>
> This is a crappy design, but I couldn't imagine anything better... so If you could help me with that I would be very happy to change it :)
>
> Best Regards
>
>
>
> 2012/1/12 Sciss
> the problem arises as you use T in any method
>
> trait Foo[T] { def lala: T }
>
> what would Twice return? the only possible solution would be that T is the common supertype of Int and String, then Twice would be a Foo[Any] and could faithfully return either a String or an Int from `lala`.
>
> i ran into this problem before, too, but when you carefully think about it, the idea of inheriting a trait twice with different type arguments is flawed.
>
> so what is it exactly that you try to achieve with Twice?
>
> best, -sciss-
>
>
> On 12 Jan 2012, at 18:22, Edmondo Porcu wrote:
>
> > Yes I realized that just after writing the email... so what is the best pattern to do that???
> >
> > trait FooString extends Foo[String]
> > trait FooInt extends Foo[Int]
> >
> > class Twice extends FooString with FooInt ?
> >
> > Best Regards
> >
> > 2012/1/12 Matthew Pocock
> > Hi Edmondo,
> >
> > This isn't possible. The JVM/bytecode representation of classes erases the type of generic parameters, so it wouldn't be able to tell Foo[String] from Foo[Int] appart in your implementation.
> >
> > trait Foo[T] {
> > def foo(t: T)
> > }
> >
> > class Twice extends Foo[String] with Foo[Int] // no good, as Foo[String] and Foo[Int] become Foo[_]
> >
> > The way I achieve this kind of thing is to use type classes and implicits.
> >
> > class Twice
> >
> > trait Foo[T] {
> > def foo(t: T): Unit
> > }
> >
> > object Foo {
> > implicit stringFoo: Foo[String] = new Foo[String] {
> > def foo(s: String): Unit = println("Got string " + s)
> > }
> >
> > implicit intFoo: Foo[Int] = new Foo[Int] {
> > def foo(i: Int): Unit = println("Got int " + i)
> > }
> > }
> >
> >
> > def twiceHandler[T](twice: Twice, t: T)(implicitly tFoo: Foo[T]): Unit = {
> > println("In twice handler")
> > tFoo.foo(t)
> > }
> >
> > Matthew
> >
> >
> > On 12 January 2012 18:07, Edmondo Porcu wrote:
> > Dear All,
> >
> > I would like to write a class who extend the same trait twice, with a different generic parameter.
> >
> > This is not possible, what is the best way to achieve that?
> >
> > Best Regards
> >
> > Edmondo
> >
> >
> >
> > --
> > Dr Matthew Pocock
> > Integrative Bioinformatics Group, School of Computing Science, Newcastle University
> > mailto: turingatemyhamster@gmail.com
> > gchat: turingatemyhamster@gmail.com
> > msn: matthew_pocock@yahoo.co.uk
> > irc.freenode.net: drdozer
> > skype: matthew.pocock
> > tel: (0191) 2566550
> > mob: +447535664143
> >
> >
>
>
Thu, 2012-01-12, 21:21
#6
Re: Re: Extending the same trait with two different generic par
You mean like this?
trait Mood { def smiley: String }
trait Sad extends Mood { def smiley = ":(" }
trait Happy extends Mood { def smiley = ":)" }
class PeopleCollection[A <: Mood] {
private[this] var people: List[A] = Nil
def who = people
def +=(a: A) { people = a :: people }
override def toString = people.map(_.smiley).mkString("d|"," ","|_") // ASCII art of people in bus
}
class SadPeopleCollection extends PeopleCollection[Sad]
class HappyPeopleCollection extends PeopleCollection[Happy]
def groupByMood(ppl: Iterable[PeopleCollection[_]]) = {
val sad = ppl.collect { case x: SadPeopleCollection => x }
val happy = ppl.collect { case x: HappyPeopleCollection => x }
(sad, happy)
}
// Test to paste into REPL
val sad1 = new SadPeopleCollection
sad1 += new Sad {}
sad1 += new Sad {}
val sad2 = new SadPeopleCollection
sad2 += new Sad {}
val happy1 = new HappyPeopleCollection
happy1 += new Happy {}
groupByMood( List(sad2, happy1, sad1) )
--Rex
On Thu, Jan 12, 2012 at 2:59 PM, <edmondo.porcu@gmail.com> wrote:
trait Mood { def smiley: String }
trait Sad extends Mood { def smiley = ":(" }
trait Happy extends Mood { def smiley = ":)" }
class PeopleCollection[A <: Mood] {
private[this] var people: List[A] = Nil
def who = people
def +=(a: A) { people = a :: people }
override def toString = people.map(_.smiley).mkString("d|"," ","|_") // ASCII art of people in bus
}
class SadPeopleCollection extends PeopleCollection[Sad]
class HappyPeopleCollection extends PeopleCollection[Happy]
def groupByMood(ppl: Iterable[PeopleCollection[_]]) = {
val sad = ppl.collect { case x: SadPeopleCollection => x }
val happy = ppl.collect { case x: HappyPeopleCollection => x }
(sad, happy)
}
// Test to paste into REPL
val sad1 = new SadPeopleCollection
sad1 += new Sad {}
sad1 += new Sad {}
val sad2 = new SadPeopleCollection
sad2 += new Sad {}
val happy1 = new HappyPeopleCollection
happy1 += new Happy {}
groupByMood( List(sad2, happy1, sad1) )
--Rex
On Thu, Jan 12, 2012 at 2:59 PM, <edmondo.porcu@gmail.com> wrote:
Yes... You are right. Let's make an example:
There is a set of people... Each of them has a state: sad or happy.
A sad person can be guided for a city tour only by a SadGuide and a happy person can be guided only by an happy guide.
Let's say now you are a company, what would you like to do? Well... Make tours for group of people, because it's more efficient. So you create your collection of people, PeopleCollection.
If all the people are sad, you can guide all them only with a SadGuide, if they are all happy with a HappyGuide. If they differ, you can't create your PeopleCollection.
I am trying to achieve this behaviour... Now imagine to add another layer.
You have a office which groups the people , and you have to decide how many sad tours you have to organize and how many happy tours. You receive a collection of PeopleCollection from the other office, and you want to divide them. You try to collect and because of pattern matching, your collect doesn't work.
I got always stucked with erasure... In every possible implementation I imagined...
Thank you for your precious help
Edmondo
Inviato da BlackBerry(R) Wireless Handheld
-----Original Message-----
From: Sciss <contact@sciss.de>
Date: Thu, 12 Jan 2012 19:31:08
To: Edmondo Porcu<edmondo.porcu@gmail.com>; scala-user<scala-user@googlegroups.com>
Subject: Re: [scala-user] Extending the same trait with two different generic parameters
sorry, i still don't understand what you want to do.
so `MyObj` == `T` and `T` is a sealed trait with three subtypes? Do items hold only one subtype of `T`, or a mix? and what is `apply` supposed to do?
maybe if you try to formulate _what_ exactly you want to do, in plain words, without the _how_, we can try to find out what is the best _how_?
best, -sciss-
On 12 Jan 2012, at 18:48, Edmondo Porcu wrote:
> Yes it is a design flaw, which I am not able to solve.
>
> The idea is the following:
>
> I have a special collections of item , let's say
>
> class MySpecialCollection(val items:IndexedSeq[MyObj]);
>
> this will support a given method for example apply (t:T) where T<:Something.
>
> However, this T-type depends on the items inside the collection, so I cannot determine it in advance...and since T can be only of three different subclasses.... I ended up doing something like that:
>
> class MySpecialCollectionForT1 {
>
> apply(t:T1) = do smth
> apply(t:T2) = throw new UnsupportedOperationException
> apply(t:T3) = throw new UnsupportedOperationException
>
> }
>
> This is a crappy design, but I couldn't imagine anything better... so If you could help me with that I would be very happy to change it :)
>
> Best Regards
>
>
>
> 2012/1/12 Sciss <contact@sciss.de>
> the problem arises as you use T in any method
>
> trait Foo[T] { def lala: T }
>
> what would Twice return? the only possible solution would be that T is the common supertype of Int and String, then Twice would be a Foo[Any] and could faithfully return either a String or an Int from `lala`.
>
> i ran into this problem before, too, but when you carefully think about it, the idea of inheriting a trait twice with different type arguments is flawed.
>
> so what is it exactly that you try to achieve with Twice?
>
> best, -sciss-
>
>
> On 12 Jan 2012, at 18:22, Edmondo Porcu wrote:
>
> > Yes I realized that just after writing the email... so what is the best pattern to do that???
> >
> > trait FooString extends Foo[String]
> > trait FooInt extends Foo[Int]
> >
> > class Twice extends FooString with FooInt ?
> >
> > Best Regards
> >
> > 2012/1/12 Matthew Pocock <turingatemyhamster@gmail.com>
> > Hi Edmondo,
> >
> > This isn't possible. The JVM/bytecode representation of classes erases the type of generic parameters, so it wouldn't be able to tell Foo[String] from Foo[Int] appart in your implementation.
> >
> > trait Foo[T] {
> > def foo(t: T)
> > }
> >
> > class Twice extends Foo[String] with Foo[Int] // no good, as Foo[String] and Foo[Int] become Foo[_]
> >
> > The way I achieve this kind of thing is to use type classes and implicits.
> >
> > class Twice
> >
> > trait Foo[T] {
> > def foo(t: T): Unit
> > }
> >
> > object Foo {
> > implicit stringFoo: Foo[String] = new Foo[String] {
> > def foo(s: String): Unit = println("Got string " + s)
> > }
> >
> > implicit intFoo: Foo[Int] = new Foo[Int] {
> > def foo(i: Int): Unit = println("Got int " + i)
> > }
> > }
> >
> >
> > def twiceHandler[T](twice: Twice, t: T)(implicitly tFoo: Foo[T]): Unit = {
> > println("In twice handler")
> > tFoo.foo(t)
> > }
> >
> > Matthew
> >
> >
> > On 12 January 2012 18:07, Edmondo Porcu <edmondo.porcu@gmail.com> wrote:
> > Dear All,
> >
> > I would like to write a class who extend the same trait twice, with a different generic parameter.
> >
> > This is not possible, what is the best way to achieve that?
> >
> > Best Regards
> >
> > Edmondo
> >
> >
> >
> > --
> > Dr Matthew Pocock
> > Integrative Bioinformatics Group, School of Computing Science, Newcastle University
> > mailto: turingatemyhamster@gmail.com
> > gchat: turingatemyhamster@gmail.com
> > msn: matthew_pocock@yahoo.co.uk
> > irc.freenode.net: drdozer
> > skype: matthew.pocock
> > tel: (0191) 2566550
> > mob: +447535664143
> >
> >
>
>
Fri, 2012-01-13, 16:51
#7
Re: Re: Extending the same trait with two different generic par
On 12 January 2012 19:59, <edmondo.porcu@gmail.com> wrote:
I find this much easier to understand with your more fully worked example. I've not compiled any of this so...
sealed trait Moodcase object Happy extends Moodcase object Sad extends Mood
case class Person[M <: Mood](m: M) { override def toString = m match { case Sad => ";(" case Happy => ":)" }}
object Person { type SadPerson = Person[Sad] type HappyPerson = Person[Happy] }
trait Guide[M <: Mood] { def takeTour(people: Set[Person[M]]) }
trait Tour { def runTour()}
class SadGuide extends Guide[Sad] { def takeTour(people: Set[SadPerson]) = println("To the graveyards... " + people.mkString("<8|", "|", "|8>") }
class HappyGuide extends Guide[Happy] { def takeTour(people: Set[Person]) = println("To the theatres... " + people.mkString("<8|", "|", "|8>") }
type PeopleCollection[M <: Mood] = Set[Person[M]]type SadPeople = PeopleCollection[Sad]type HappyPeople = PeopleCollection[Happy]
object TourCompany { def sadTour(people: SadPeople) = (new SadGuide).takeTour(people) def happyTour(people: HappyPeople) = (new HappyGuide).tateTour(people)
def tour[M <: Mood](people: PeopleCollection[M]) = { val sad = people.collect { case p@Person(Sad) => p } val happy = people.collect { case p@Person(Happy) => p } sadTour(sad) happyTour(happy) }}
Not sure if this code compiles - I was just typing and thinking.
Matthew
--
Dr Matthew PocockIntegrative Bioinformatics Group, School of Computing Science, Newcastle Universitymailto: turingatemyhamster@gmail.com gchat: turingatemyhamster@gmail.commsn: matthew_pocock@yahoo.co.uk irc.freenode.net: drdozerskype: matthew.pococktel: (0191) 2566550mob: +447535664143
Yes... You are right. Let's make an example:Hi Edomondo,
I find this much easier to understand with your more fully worked example. I've not compiled any of this so...
There is a set of people... Each of them has a state: sad or happy.
sealed trait Moodcase object Happy extends Moodcase object Sad extends Mood
case class Person[M <: Mood](m: M) { override def toString = m match { case Sad => ";(" case Happy => ":)" }}
object Person { type SadPerson = Person[Sad] type HappyPerson = Person[Happy] }
A sad person can be guided for a city tour only by a SadGuide and a happy person can be guided only by an happy guide.
trait Guide[M <: Mood] { def takeTour(people: Set[Person[M]]) }
trait Tour { def runTour()}
class SadGuide extends Guide[Sad] { def takeTour(people: Set[SadPerson]) = println("To the graveyards... " + people.mkString("<8|", "|", "|8>") }
class HappyGuide extends Guide[Happy] { def takeTour(people: Set[Person]) = println("To the theatres... " + people.mkString("<8|", "|", "|8>") }
Let's say now you are a company, what would you like to do? Well... Make tours for group of people, because it's more efficient. So you create your collection of people, PeopleCollection.
type PeopleCollection[M <: Mood] = Set[Person[M]]type SadPeople = PeopleCollection[Sad]type HappyPeople = PeopleCollection[Happy]
If all the people are sad, you can guide all them only with a SadGuide, if they are all happy with a HappyGuide. If they differ, you can't create your PeopleCollection.
object TourCompany { def sadTour(people: SadPeople) = (new SadGuide).takeTour(people) def happyTour(people: HappyPeople) = (new HappyGuide).tateTour(people)
I am trying to achieve this behaviour... Now imagine to add another layer.
You have a office which groups the people , and you have to decide how many sad tours you have to organize and how many happy tours. You receive a collection of PeopleCollection from the other office, and you want to divide them. You try to collect and because of pattern matching, your collect doesn't work.
def tour[M <: Mood](people: PeopleCollection[M]) = { val sad = people.collect { case p@Person(Sad) => p } val happy = people.collect { case p@Person(Happy) => p } sadTour(sad) happyTour(happy) }}
I got always stucked with erasure... In every possible implementation I imagined...
Thank you for your precious help
Not sure if this code compiles - I was just typing and thinking.
Matthew
Edmondo
Inviato da BlackBerry(R) Wireless Handheld
-----Original Message-----
From: Sciss <contact@sciss.de>
Date: Thu, 12 Jan 2012 19:31:08
To: Edmondo Porcu<edmondo.porcu@gmail.com>; scala-user<scala-user@googlegroups.com>
Subject: Re: [scala-user] Extending the same trait with two different generic parameters
sorry, i still don't understand what you want to do.
so `MyObj` == `T` and `T` is a sealed trait with three subtypes? Do items hold only one subtype of `T`, or a mix? and what is `apply` supposed to do?
maybe if you try to formulate _what_ exactly you want to do, in plain words, without the _how_, we can try to find out what is the best _how_?
best, -sciss-
On 12 Jan 2012, at 18:48, Edmondo Porcu wrote:
> Yes it is a design flaw, which I am not able to solve.
>
> The idea is the following:
>
> I have a special collections of item , let's say
>
> class MySpecialCollection(val items:IndexedSeq[MyObj]);
>
> this will support a given method for example apply (t:T) where T<:Something.
>
> However, this T-type depends on the items inside the collection, so I cannot determine it in advance...and since T can be only of three different subclasses.... I ended up doing something like that:
>
> class MySpecialCollectionForT1 {
>
> apply(t:T1) = do smth
> apply(t:T2) = throw new UnsupportedOperationException
> apply(t:T3) = throw new UnsupportedOperationException
>
> }
>
> This is a crappy design, but I couldn't imagine anything better... so If you could help me with that I would be very happy to change it :)
>
> Best Regards
>
>
>
> 2012/1/12 Sciss <contact@sciss.de>
> the problem arises as you use T in any method
>
> trait Foo[T] { def lala: T }
>
> what would Twice return? the only possible solution would be that T is the common supertype of Int and String, then Twice would be a Foo[Any] and could faithfully return either a String or an Int from `lala`.
>
> i ran into this problem before, too, but when you carefully think about it, the idea of inheriting a trait twice with different type arguments is flawed.
>
> so what is it exactly that you try to achieve with Twice?
>
> best, -sciss-
>
>
> On 12 Jan 2012, at 18:22, Edmondo Porcu wrote:
>
> > Yes I realized that just after writing the email... so what is the best pattern to do that???
> >
> > trait FooString extends Foo[String]
> > trait FooInt extends Foo[Int]
> >
> > class Twice extends FooString with FooInt ?
> >
> > Best Regards
> >
> > 2012/1/12 Matthew Pocock <turingatemyhamster@gmail.com>
> > Hi Edmondo,
> >
> > This isn't possible. The JVM/bytecode representation of classes erases the type of generic parameters, so it wouldn't be able to tell Foo[String] from Foo[Int] appart in your implementation.
> >
> > trait Foo[T] {
> > def foo(t: T)
> > }
> >
> > class Twice extends Foo[String] with Foo[Int] // no good, as Foo[String] and Foo[Int] become Foo[_]
> >
> > The way I achieve this kind of thing is to use type classes and implicits.
> >
> > class Twice
> >
> > trait Foo[T] {
> > def foo(t: T): Unit
> > }
> >
> > object Foo {
> > implicit stringFoo: Foo[String] = new Foo[String] {
> > def foo(s: String): Unit = println("Got string " + s)
> > }
> >
> > implicit intFoo: Foo[Int] = new Foo[Int] {
> > def foo(i: Int): Unit = println("Got int " + i)
> > }
> > }
> >
> >
> > def twiceHandler[T](twice: Twice, t: T)(implicitly tFoo: Foo[T]): Unit = {
> > println("In twice handler")
> > tFoo.foo(t)
> > }
> >
> > Matthew
> >
> >
> > On 12 January 2012 18:07, Edmondo Porcu <edmondo.porcu@gmail.com> wrote:
> > Dear All,
> >
> > I would like to write a class who extend the same trait twice, with a different generic parameter.
> >
> > This is not possible, what is the best way to achieve that?
> >
> > Best Regards
> >
> > Edmondo
> >
> >
> >
> > --
> > Dr Matthew Pocock
> > Integrative Bioinformatics Group, School of Computing Science, Newcastle University
> > mailto: turingatemyhamster@gmail.com
> > gchat: turingatemyhamster@gmail.com
> > msn: matthew_pocock@yahoo.co.uk
> > irc.freenode.net: drdozer
> > skype: matthew.pocock
> > tel: (0191) 2566550
> > mob: +447535664143
> >
> >
>
>
--
Dr Matthew PocockIntegrative Bioinformatics Group, School of Computing Science, Newcastle Universitymailto: turingatemyhamster@gmail.com gchat: turingatemyhamster@gmail.commsn: matthew_pocock@yahoo.co.uk irc.freenode.net: drdozerskype: matthew.pococktel: (0191) 2566550mob: +447535664143
the problem arises as you use T in any method
trait Foo[T] { def lala: T }
what would Twice return? the only possible solution would be that T is the common supertype of Int and String, then Twice would be a Foo[Any] and could faithfully return either a String or an Int from `lala`.
i ran into this problem before, too, but when you carefully think about it, the idea of inheriting a trait twice with different type arguments is flawed.
so what is it exactly that you try to achieve with Twice?
best, -sciss-
On 12 Jan 2012, at 18:22, Edmondo Porcu wrote:
> Yes I realized that just after writing the email... so what is the best pattern to do that???
>
> trait FooString extends Foo[String]
> trait FooInt extends Foo[Int]
>
> class Twice extends FooString with FooInt ?
>
> Best Regards
>
> 2012/1/12 Matthew Pocock
> Hi Edmondo,
>
> This isn't possible. The JVM/bytecode representation of classes erases the type of generic parameters, so it wouldn't be able to tell Foo[String] from Foo[Int] appart in your implementation.
>
> trait Foo[T] {
> def foo(t: T)
> }
>
> class Twice extends Foo[String] with Foo[Int] // no good, as Foo[String] and Foo[Int] become Foo[_]
>
> The way I achieve this kind of thing is to use type classes and implicits.
>
> class Twice
>
> trait Foo[T] {
> def foo(t: T): Unit
> }
>
> object Foo {
> implicit stringFoo: Foo[String] = new Foo[String] {
> def foo(s: String): Unit = println("Got string " + s)
> }
>
> implicit intFoo: Foo[Int] = new Foo[Int] {
> def foo(i: Int): Unit = println("Got int " + i)
> }
> }
>
>
> def twiceHandler[T](twice: Twice, t: T)(implicitly tFoo: Foo[T]): Unit = {
> println("In twice handler")
> tFoo.foo(t)
> }
>
> Matthew
>
>
> On 12 January 2012 18:07, Edmondo Porcu wrote:
> Dear All,
>
> I would like to write a class who extend the same trait twice, with a different generic parameter.
>
> This is not possible, what is the best way to achieve that?
>
> Best Regards
>
> Edmondo
>
>
>