<https://twitter.com/arrow_kt/status/1135961780377...
# feed
r
b
@raulraja I'm pretty excited about Typeclasses in Kotlin, just one doubt about it, are we going to have a solution for orphan implementations? I have a module with my
Repository
, can I from another module create something like:
Copy code
fun login(password: String, with repo: Repository<Login>) {
    loginWith(password)
}
I saw the section of
Subpackes
on this text and I understand the problem about it but I think it's important we have a solution for that. For example the compiler looks for the extension by the import.
r
yes, that is a declaration and could be in any other module. It's in call sites where resolution and injection happens. If you define orphan overrides they need to be marked as
internal
so you can use them in your apps just fine but they can't be consumed from external packages.
👍 1
The internal mechanism and preserving coherence with only internal overrides is not discarded and we will added based on feedback
n
honestly, i find this would be a step toward more convoluted code what i dislike in scala, and like in kotlin, is explicitness e.g. no
implicit
keyword the process of the compiler implicitly searching in different locations for the equality is a step in this (wrong for me) direction
👍 2
sorry to break the mood...
but thanks for the post, it states the problem clearly
r
For what is worth the Kotlin compiler already has implicits. Extension and Receiver functions are no different than one argument implicits. The widespread use of spring and dagger in Kotlin and java land are proof these features are very much needed and liked by most developers. Everyone that uses dagger or any DI framework uses a form of implicits. What Kotlin lacks today IMO is a way to refer to extension families so we can activate syntax over types without a bunch of imports. IDEA can also highlight which instance value is assigning on each call site but resolution as proposed is so simple that is easy to understand where things are coming from since scoping is just global unlike in Scala
n
extensions are by no way implicit! i can click on my extension function, and intellij will show me the place where it has been defined likewise, using spring and dagger are invalid arguments you can use spring with explicit dependency injection (i’ve already written about it https://blog.frankel.ch/my-case-against-autowiring/) so, you cannot use those arguments to claim
[implicit] is liked by most developers
on the other hand, spring fu shows the trend is to migrate to explicitness my point still stands
that is easy to understand where things are coming from
just no it’s not because you know that it’s easy
b
I think the implicity about extensions functions are about how its bytecode is created and following this logic you also can click on your typeclass and see where it's been created, no? Probably the comparation of implicity of a typeclass and an extension function is about how compiler resolve them.
n
you also can click on your typeclass and see where it’s been created
perhaps... but then i misread the initial article because i understood differently
r
@bloder exactly
additionally extensions are implicit arguments which then are made concrete by a proof for example:
Copy code
fun <A> A.foo() = TODO()
scala
Copy code
implicit class FooSyntax[A](a: A) {
  def foo(): Unit = ???
}
Kotlin simplifies the boilerplate in the user side compared to Scala 2.12 (in Scala 3 is the same as in Kotlin) but the argument and the receiver is still implicit since it’s provided in the call site without explicitly being passed by the user as a function argument. KEEP-87 proposes the same as extension functions but you can then name a group of extensions. Once you have a name you can add that name as a constrain to activate the syntax a la carte where you need it. And that in fact is implicit argument injection same as in any DI framework despite people hating and being confused by scala implicits. Scala implicits are overkill IMO and have been abused and that is why they are getting rid of them in Scala 3 in favor of idioms that do the same thing but are use case specific. Swift, Scala and pretty much all moderns languages support a form of composition that is not through inheritance. @nfrankel your case against autowiring does not apply to the KEEP-87 proposal because type classes as proposed are coherent and orphan overrides if permitted are internal and can’t be exported outside of the module for compiler resolution.
The compiler only looks in the packages of the typeclass or the ones of the data type and only allows programs to compile when a single cannonical instance is in scope.
If you choose to override that behavior your instance is internal an can’t be exported for third party consumption
Also granted the IDE will take you from the point of injection straight to the definition and all call sites because the compiler already knows that before you have the chance to finish your compilation.
b
@raulraja what are the next steps to merge this KEEP? What is missing in its definition?
r
@bloder We are awaiting feedback from the compiler team before we keep on iterating.
👍 1
@nfrankel I think your article makes sense in the context of Spring or frameworks where this is an issue but this problem can be solved in many other ways