Proposal: consider implicit members of receiver object

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Proposal: consider implicit members of receiver object

Jason Zaugg
Is there deliberate design decision that prevents the following?

scala> class Foo { implicit def asString = "Foo" }
defined class Foo

scala> new Foo : String
<console>:6: error: type mismatch;

Recently [1] [2], I proposed on scala-debate that Seq[A] should not
inherit from PartialFunction[Int, A], but instead project an implicit
view. This was motivated personally by the unfortunate interaction
between contra-variance, type inference, and implicit search. See the
details at the bottom of the mail. In addition, it would allow useful
(fundamental?) methods to be added to FunctionN without the objection
that they would clash with the semantics of the overriding methods in
Seq, notably map/flatMap. [3]

To make this change and largely preserve backwards compatibility, the
implicit conversion method would need to be defined in Predef (or
possibly in Function1). While this is feasible for the implementors of
Scala, a normal library could not make such a change. If the language
considered implicit members on the receiver object, this limitation
would be removed.

  trait Seq[A] extends ... {
     implicit toPartialFunction: PartialFunction[Int, A] = // ...
  }

One could also imagine a syntactic sugar for this:

  trait Seq[A] projects PartialFunction[Int, A]

Which could compile to:

  trait Seq[A] {
     implicit `toPartialFunction[Int,A]$` PartialFunction[Int, A] = this
  }

-jason

[1] http://article.gmane.org/gmane.comp.lang.scala.debate/4030
[2] http://article.gmane.org/gmane.comp.lang.scala.debate/4031
[3] http://www.scala-lang.org/node/4338#comment-17940


trait TypeClass[-A]

object TypeClass {
   def FunctionInstance[A]: TypeClass[PartialApply1of2[Function1,
A]#Apply] = // ...
   def StreamInstance: TypeClass[Stream] = // ..
}

implicitly[TypeClass[Stream]] // gives FunctionInstance, but I want
StreamInstance
}
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: consider implicit members of receiver object

Daniel Sobral
This works:
 
class Foo
object Foo {
implicit def asString(f: Foo) = "Foo"
}
 
Works with implicits too:
 
trait Bar
object Bar {
  implicit def asString(b: Bar) = "Bar"
}
class Foobar extends Bar
 
In both cases, new XXX : String will work.

On Mon, Jan 4, 2010 at 7:28 AM, Jason Zaugg <[hidden email]> wrote:
Is there deliberate design decision that prevents the following?

scala> class Foo { implicit def asString = "Foo" }
defined class Foo

scala> new Foo : String
<console>:6: error: type mismatch;

Recently [1] [2], I proposed on scala-debate that Seq[A] should not
inherit from PartialFunction[Int, A], but instead project an implicit
view. This was motivated personally by the unfortunate interaction
between contra-variance, type inference, and implicit search. See the
details at the bottom of the mail. In addition, it would allow useful
(fundamental?) methods to be added to FunctionN without the objection
that they would clash with the semantics of the overriding methods in
Seq, notably map/flatMap. [3]

To make this change and largely preserve backwards compatibility, the
implicit conversion method would need to be defined in Predef (or
possibly in Function1). While this is feasible for the implementors of
Scala, a normal library could not make such a change. If the language
considered implicit members on the receiver object, this limitation
would be removed.

 trait Seq[A] extends ... {
    implicit toPartialFunction: PartialFunction[Int, A] = // ...
 }

One could also imagine a syntactic sugar for this:

 trait Seq[A] projects PartialFunction[Int, A]

Which could compile to:

 trait Seq[A] {
    implicit `toPartialFunction[Int,A]$` PartialFunction[Int, A] = this
 }

-jason

[1] http://article.gmane.org/gmane.comp.lang.scala.debate/4030
[2] http://article.gmane.org/gmane.comp.lang.scala.debate/4031
[3] http://www.scala-lang.org/node/4338#comment-17940


trait TypeClass[-A]

object TypeClass {
  def FunctionInstance[A]: TypeClass[PartialApply1of2[Function1,
A]#Apply] = // ...
  def StreamInstance: TypeClass[Stream] = // ..
}

implicitly[TypeClass[Stream]] // gives FunctionInstance, but I want
StreamInstance
}



--
Daniel C. Sobral

I travel to the future all the time.
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: consider implicit members of receiver object

Jason Zaugg
Nope, only the companion objects of the expected type (in this case
String) and its components and supertypes are searched.

-jason

Welcome to Scala version 2.8.0.r20250-b20091221020148
scala> class Foo
defined class Foo

scala> object Foo { implicit def asString(f: Foo) = "Foo" }
defined module Foo

scala> new Foo : String
<console>:6: error: type mismatch;
 found   : Foo
 required: String
       new Foo : String
       ^

On Mon, Jan 4, 2010 at 11:50 AM, Daniel Sobral <[hidden email]> wrote:

> This works:
>
> class Foo
> object Foo {
> implicit def asString(f: Foo) = "Foo"
> }
>
> Works with implicits too:
>
> trait Bar
> object Bar {
>   implicit def asString(b: Bar) = "Bar"
> }
> class Foobar extends Bar
>
> In both cases, new XXX : String will work.
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: consider implicit members of receiver object

Jason Zaugg
In reply to this post by Jason Zaugg
I made an error in the example of my problem contra-variant implicit
search. Correction below. Also note that the type PartialApply1Of2 is
from Scalaz [1].

-jason

[1] http://code.google.com/p/scalaz/source/browse/trunk/core/src/main/scala/scalaz/PartialApply1Of2.scala

trait TypeClass[-A[_]]  // corrected from original example.

object TypeClass {
  def FunctionInstance[A]:
TypeClass[PartialApply1of2[Function1,A]#Apply] = // ...
  def StreamInstance: TypeClass[Stream] = // ..
}

implicitly[TypeClass[Stream]] // gives FunctionInstance, but I want
StreamInstance
}

> trait TypeClass[-A]
>
> object TypeClass {
>   def FunctionInstance[A]: TypeClass[PartialApply1of2[Function1,
> A]#Apply] = // ...
>   def StreamInstance: TypeClass[Stream] = // ..
> }
>
> implicitly[TypeClass[Stream]] // gives FunctionInstance, but I want
> StreamInstance
> }
>
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: consider implicit members of receiver object

Daniel Sobral
In reply to this post by Jason Zaugg
The examples I gave were tested, they work. You make the common mistake of thinking that consecutive definitions of class and object on the REPL create companionship between them -- which it does not, since each is created in a different object!
 
Instead, try this:
 
scala> object T2 {
     | trait Bar
     | object Bar {
     |   implicit def asString(b: Bar) = "Bar"
     | }
     | class Foobar extends Bar
     | }
defined module T2
scala> import T2._
import T2._
scala> new Foobar : String
res3: String = Bar
On Mon, Jan 4, 2010 at 9:06 AM, Jason Zaugg <[hidden email]> wrote:
Nope, only the companion objects of the expected type (in this case
String) and its components and supertypes are searched.

-jason

Welcome to Scala version 2.8.0.r20250-b20091221020148
scala> class Foo
defined class Foo

scala> object Foo { implicit def asString(f: Foo) = "Foo" }
defined module Foo

scala> new Foo : String
<console>:6: error: type mismatch;
 found   : Foo
 required: String
      new Foo : String
      ^

On Mon, Jan 4, 2010 at 11:50 AM, Daniel Sobral <[hidden email]> wrote:
> This works:
>
> class Foo
> object Foo {
> implicit def asString(f: Foo) = "Foo"
> }

>
> Works with implicits too:
>
> trait Bar
> object Bar {
>   implicit def asString(b: Bar) = "Bar"
> }
> class Foobar extends Bar
>
> In both cases, new XXX : String will work.



--
Daniel C. Sobral

I travel to the future all the time.
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: consider implicit members of receiver object

Jason Zaugg
Thanks for clearing that up, and sorry for the noise!

The question still stands, although merely out of curiosity, why not
also consider implicits from the receiver object itself?

-jason

On Mon, Jan 4, 2010 at 12:43 PM, Daniel Sobral <[hidden email]> wrote:
> The examples I gave were tested, they work. You make the common mistake of
> thinking that consecutive definitions of class and object on the REPL create
> companionship between them -- which it does not, since each is created in a
> different object!
Reply | Threaded
Open this post in threaded view
|

Re: Proposal: consider implicit members of receiver object

Martin Odersky
On Mon, Jan 4, 2010 at 1:07 PM, Jason Zaugg <[hidden email]> wrote:
> Thanks for clearing that up, and sorry for the noise!
>
> The question still stands, although merely out of curiosity, why not
> also consider implicits from the receiver object itself?

The main reasons for me are to keep the spec simple and to not slow
down the compiler even further when it has to search for implicits.

Cheers

 -- Martin