-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Insert traits with implicit parameters as extra parents of classes #11830
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
If a trait A extends some other trait B which takes an implicit parameter, and a class C extends A but not B, we need to insert B into the parents of A, so that the implicit argument can be generated. This required a generalization of the syncing between parent trees and parent types. Namer will augment the parent types of a class with possibly other types. Previously the only such change was a possibly leading class type, but we now also generate trait parents that take context parameters. The new method parentTrees reflects any such changes in the parent trees in Typer.
Nice! Would you mind documenting this in http://dotty.epfl.ch/docs/reference/other-new-features/trait-parameters.html ? |
Will the following code work as a result of this change ? trait Semigroup[A]:
extension (a: A) def combine(b: A): A
trait Monoid[A: Semigroup]:
def unit: A
given Semigroup[Int] with
extension (a: Int) def combine(b: Int): Int = a + b
given Monoid[Int] with
def unit: Int = 0
def sumList[A: Monoid](ls: List[A]): A = ls.foldLeft(summon[Monoid[A]].unit)(_.combine(_))
@main def Test() =
val ls = List(1,2,3)
println(sumList(ls))
|
@amsayk The change would help, but your example does not compile since |
Yeah that makes sense. Maybe an trait Semigroup[A]:
extension (a: A) def combine(b: A): A
trait Monoid[A](using S: Semigroup[A]):
export S.combine
def unit: A
given Semigroup[Int] with
extension (a: Int) def combine(b: Int): Int = a + b
given Monoid[Int] with
def unit: Int = 0
def sumList[A: Monoid](ls: List[A]): A = ls.foldLeft(summon[Monoid[A]].unit)(_.combine(_))
@main def Test() =
val ls = List(1,2,3)
println(sumList(ls))
I think this example showcases the line between OOP inheritance and addhoc polymorphism. One would intuitively think that since |
On a somewhat related note, I want to ask: The above code uses the syntax If extension methods with desugared to a single parameter group, we could simple write: def sumList[A: Monoid](ls: List[A]): A = ls.foldLeft(summon[Monoid[A]].unit)(combine) So my question is: Does this even make sense in Scala and if so what do you think about changing the encoding to single parameter group ? |
That would be ambiguous. But you can write
if you want to be more symmetric. |
Insert traits with implicit parameters as extra parents of classes
If a trait A extends some other trait B which takes an implicit parameter, and
a class C extends A but not B, we need to insert B into the parents of C, so
that the implicit argument can be generated.
This required a generalization of the syncing between parent trees and parent types.
Namer will augment the parent types of a class with possibly other types.
Previously the only such change was a possibly leading class type, but we now
also generate trait parents that take context parameters. The new method parentTrees
reflects any such changes in the parent trees in Typer.
Fixes #7613