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

Implicit view's "associated types" for implicit scope

3 replies
Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 6 days ago.
I was re-reading the spec on implicit resolution and the implicit scope of a lookup.   The wording seems to imply that, when looking for an implicit view, the implicit scope of A => B is used to find conversions if B is known.   This does not appear to be the case in reality (see below REPL session).

I totally understand in the situation where you have x.foo and foo is not a member of x's type (say type A) that you can only use the associated types of A, not A => B.   However the situation below knows what type conversions are being attempted, such as that outlined below, would it make sense to use the implicit scope of Function[B,A]?

scala> object holder {
     | trait Foo
     | trait Bar
     | object Foo {
     |   implicit def foo2bar(foo : Foo) = new Bar{}
     |   implicit def bar2foo(bar : Bar) = new Foo{}
     | }
     | }
defined module holder

scala> import holder._
import holder._

scala> val foo : Foo = new Bar {}
foo: holder.Foo = holder$Foo$$anon$2@6568f248

scala> val bar : Bar = new Foo {}   // We have the desired type, can we use it for implicit scope?
<console>:9: error: type mismatch;
 found   : java.lang.Object with holder.Foo
 required: holder.Bar
       val bar : Bar = new Foo {}
                       ^


Thanks!
- Josh
Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 6 days ago.
Re: Implicit view's "associated types" for implicit scope
I should note, that if this were alllowed, wrapping a java library in Scala would become far more elegant, ideally without issues.

As another aside, I've debating adding a 'dirty companion' annotation so that I can, for example:

-------------- some scala file ---------------------------------
package java.sql

@DirtyCompanion
object Connection {
  implicit def pimpify(conn : Connection) = new MyRichConnectionWrapper(conn)
}

It'd be an interesting way to create extensions and "shims" if you will between Scala and Java libraries.   This would be limited to one companion per class you want to extend, so it could become unwielding in practice.   However, it might add some more "smoothness" between the Scala standard library and Java's.  I'd imagine more pieces of Predef could move to companion objects.

Thoughts?
- Josh

On Tue, Nov 9, 2010 at 10:31 PM, Josh Suereth <joshua.suereth@gmail.com> wrote:
I was re-reading the spec on implicit resolution and the implicit scope of a lookup.   The wording seems to imply that, when looking for an implicit view, the implicit scope of A => B is used to find conversions if B is known.   This does not appear to be the case in reality (see below REPL session).

I totally understand in the situation where you have x.foo and foo is not a member of x's type (say type A) that you can only use the associated types of A, not A => B.   However the situation below knows what type conversions are being attempted, such as that outlined below, would it make sense to use the implicit scope of Function[B,A]?

scala> object holder {
     | trait Foo
     | trait Bar
     | object Foo {
     |   implicit def foo2bar(foo : Foo) = new Bar{}
     |   implicit def bar2foo(bar : Bar) = new Foo{}
     | }
     | }
defined module holder

scala> import holder._
import holder._

scala> val foo : Foo = new Bar {}
foo: holder.Foo = holder$Foo$$anon$2@6568f248

scala> val bar : Bar = new Foo {}   // We have the desired type, can we use it for implicit scope?
<console>:9: error: type mismatch;
 found   : java.lang.Object with holder.Foo
 required: holder.Bar
       val bar : Bar = new Foo {}
                       ^


Thanks!
- Josh

Jason Zaugg
Joined: 2009-05-18,
User offline. Last seen 38 weeks 5 days ago.
Re: Implicit view's "associated types" for implicit scope

This works:

implicitly[Foo => Bar] // okay
(new Foo{}: Foo): Bar // okay
trait Flup extends Foo
implicitly[Flup => Bar]

This doesn't:

(new Foo{}) : Bar // boom!

Maybe it's a bug. I haven't traced through the compiler to see where
the difference emerges.

-jason

On Wed, Nov 10, 2010 at 4:31 AM, Josh Suereth wrote:
> I was re-reading the spec on implicit resolution and the implicit scope of a
> lookup.   The wording seems to imply that, when looking for an implicit
> view, the implicit scope of A => B is used to find conversions if B is
> known.   This does not appear to be the case in reality (see below REPL
> session).
>
> I totally understand in the situation where you have x.foo and foo is not a
> member of x's type (say type A) that you can only use the associated types
> of A, not A => B.   However the situation below knows what type conversions
> are being attempted, such as that outlined below, would it make sense to use
> the implicit scope of Function[B,A]?
>
> scala> object holder {
>      | trait Foo
>      | trait Bar
>      | object Foo {
>      |   implicit def foo2bar(foo : Foo) = new Bar{}
>      |   implicit def bar2foo(bar : Bar) = new Foo{}
>      | }
>      | }
> defined module holder
>
> scala> import holder._
> import holder._
>
> scala> val foo : Foo = new Bar {}
> foo: holder.Foo = holder$Foo$$anon$2@6568f248
>
> scala> val bar : Bar = new Foo {}   // We have the desired type, can we use
> it for implicit scope?
> :9: error: type mismatch;
>  found   : java.lang.Object with holder.Foo
>  required: holder.Bar
>        val bar : Bar = new Foo {}
>                        ^
>
>
> Thanks!
> - Josh
>

odersky
Joined: 2008-07-29,
User offline. Last seen 45 weeks 6 days ago.
Re: Implicit view's "associated types" for implicit scope


On Wed, Nov 10, 2010 at 8:05 AM, Jason Zaugg <jzaugg@gmail.com> wrote:
This works:

implicitly[Foo => Bar] // okay
(new Foo{}: Foo): Bar  // okay
trait Flup extends Foo
implicitly[Flup => Bar]

This doesn't:

(new Foo{}) : Bar      // boom!

Maybe it's a bug. I haven't traced through the compiler to see where
the difference emerges.

I might have an idea what causes this. Essentially, (new Foo {}) is itself a shorthand for

  { class anon extends Foo {}; new anon }

and that is tricky to type because the natural type would be anon, but that one is illegal because it escapes its scope. So it uses the prototype, Bar in this case. It might well be that at the place where this happens, implicit conversions are not attempted. Josh, can you please file a ticket, then it won't be forgotten. You can assign to me directly.

Thanks

 - Martin

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