This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Is there a way to infer the type here

3 replies
ojow
Joined: 2009-10-21,
User offline. Last seen 37 weeks 3 days ago.

trait A[T <: A[T]]
trait B
class C extends A[C]

object MiniTest {
def foo[T <: A[T]](x: T with B) { println ("hi") }

def main(args: Array[String]) {
val bar = new C with B
foo[C](bar) // ok
foo(bar) // error
}
}

Is there a way to make foo(bar) work without specifying [C]?
Thanks.

milessabin
Joined: 2008-08-11,
User offline. Last seen 33 weeks 3 days ago.
Re: Is there a way to infer the type here

On Sat, Jan 9, 2010 at 12:59 PM, Oleg G wrote:
> trait A[T <: A[T]]
> trait B
> class C extends A[C]
>
> object MiniTest {
>  def foo[T <: A[T]](x: T with B) { println ("hi") }
>
>  def main(args: Array[String]) {
>    val bar = new C with B
>    foo[C](bar) // ok
>    foo(bar) // error
>  }
> }
>
> Is there a way to make foo(bar) work without specifying [C]?

Welcome to Scala version 2.8.0.r20054-b20100107214002 (Java
HotSpot(TM) Server VM, Java 1.6.0_14).
Type in expressions to have them evaluated.
Type :help for more information.

scala> trait A[T <: A[T]]
defined trait A

scala> trait B
defined trait B

scala> class C extends A[C]
defined class C

scala> def foo[T <: A[T]](x: T with B) { println ("hi") }
foo: [T <: A[T]](x: T with B)Unit

scala> val bar = new C with B
bar: C with B = $anon$1@1264666

scala> def foo[T <: A[T]](x: A[T] with B) { println ("hi") }
foo: [T <: A[T]](x: A[T] with B)Unit

scala> foo(bar)
hi

ojow
Joined: 2009-10-21,
User offline. Last seen 37 weeks 3 days ago.
Re: Is there a way to infer the type here

Thanks. And as i can understand the way scala works here even doesn't
need any imporvement because there is no case where we logically need
the T itself, A[T] is always enough. Though i had to cast A[T] to T
(always safe, right?) in a piece of code like following:

trait SomeTrait[T] { def field: T }

def foo[T <: A[T]](x: A[T] with B) {
// ...
val a = new SomeTrait[T] { override def field: T = x.asInstanceOf[T] }
//...
}

2010/1/9 Miles Sabin :
> On Sat, Jan 9, 2010 at 12:59 PM, Oleg G wrote:
>> trait A[T <: A[T]]
>> trait B
>> class C extends A[C]
>>
>> object MiniTest {
>>  def foo[T <: A[T]](x: T with B) { println ("hi") }
>>
>>  def main(args: Array[String]) {
>>    val bar = new C with B
>>    foo[C](bar) // ok
>>    foo(bar) // error
>>  }
>> }
>>
>> Is there a way to make foo(bar) work without specifying [C]?
>
> Welcome to Scala version 2.8.0.r20054-b20100107214002 (Java
> HotSpot(TM) Server VM, Java 1.6.0_14).
> Type in expressions to have them evaluated.
> Type :help for more information.
>
> scala> trait A[T <: A[T]]
> defined trait A
>
> scala> trait B
> defined trait B
>
> scala> class C extends A[C]
> defined class C
>
> scala> def foo[T <: A[T]](x: T with B) { println ("hi") }
> foo: [T <: A[T]](x: T with B)Unit
>
> scala> val bar = new C with B
> bar: C with B = $anon$1@1264666
>
> scala> def foo[T <: A[T]](x: A[T] with B) { println ("hi") }
> foo: [T <: A[T]](x: A[T] with B)Unit
>
> scala> foo(bar)
> hi
>
> --
> Miles Sabin
> tel: +44 (0)7813 944 528
> skype:  milessabin
> http://www.chuusai.com/
> http://twitter.com/milessabin
>

ewilligers
Joined: 2008-08-20,
User offline. Last seen 3 years 17 weeks ago.
Re: Is there a way to infer the type here

Oleg G wrote:
> Thanks. And as i can understand the way scala works here even doesn't
> need any imporvement because there is no case where we logically need
> the T itself, A[T] is always enough. Though i had to cast A[T] to T
> (always safe, right?) in a piece of code like following:
>
> trait SomeTrait[T] { def field: T }
>
> def foo[T <: A[T]](x: A[T] with B) {
> // ...
> val a = new SomeTrait[T] { override def field: T = x.asInstanceOf[T] }
> //...
> }

Here are two ways to avoid the cast:-

def foo[T <: A[T]](x: A[T] with B with T)

OR

trait A[T <: A[T]] { this: T => def self: T = this }

def foo[T <: A[T]](x: A[T] with B) {
...
def field: T = x.self
...
}

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland