Are there ideas about extension interface implemen...
# language-evolution
a
Are there ideas about extension interface implementations? At the moment we can create extension functions, but I would find it very interesting if it would be possible to implement an interface by extension. Basically it would boil down to traits. I like the idea of adding behavior to data structures you do not own.
y
Context parameters can already get you pretty far, although you have to restructure your code. There's sadly no "lookup" mechanism for them though.
Copy code
interface Monoid<M> {
  val zero: M
  operator fun M.plus(other: M): M
}
// Contextual bridge functions
context(m: Monoid<M>)
val <M> zero: M get() = m.zero
context(m: Monoid<M>)
operator fun <M> M.plus(other: M): M = with(m) { this@plus + other }

// Usage
context(m: Monoid<M>)
fun <M> Iterable<M>.sum() = fold(zero) { a, b -> a + b }
a
Looks great. How would I implement Monoid then for a a custom datastructure? As an object implementation?
y
Yep:
Copy code
object IntMonoid: Monoid<Int> {
  override val zero = 0
  override fun Int.plus(other: Int) = this + other
}
The annoying part is you need to explicitly bring in
IntMonoid
:
Copy code
context(IntMonoid) {
  listOf(1, 2, 3).sum()
}
a
Interesting. It has quite a lot of overlap with traits
c
I use Interface delegation pretty frequently to build trait-like functionality in my apps https://kotlinlang.org/docs/delegation.html
a
@Casey Brooks This is subtly different and I use this as well. But this is composition of behavior where the class using the interfaces is owned by you. So, you have
MyData(val delegate: Interface A) : Interface A by delegate
. But what I mean is is that I am not able to change MyData. It is external library and I only know it is
class MyData
. However, I want to implement InterfaceA for it, which consists out of
Copy code
interface InterfaceA {
   foo(): Int
   bar(): String
}
I could just create the separate extension functions:
Copy code
fun MyData.foo(): Int = ...
fun MyData.bar(): Int = ...
but that still doesn't make it an Interface A. What I would like to (pseudecode):
Copy code
implement MyData : InterfaceA {
  foo(): Int { ... }
   ba(): Int { ... }
}
Which allows me to add an implementation of InterfaceA to MyData, even though I do not own it. This looks a lot like Rust ofcourse:
Copy code
impl MyTrait for MyData {}
c
Additionally, if you have:
Copy code
// External code
interface Ext

// Your code
interface Additional
you can also:
Copy code
class Wrapped(val ext: Ext) : Ext by ext, Additional {
    …
}
It's essentially the same approach as Youssef's context parameters approach, but it binds the implementation in a wrapper so you don't need to pass around the context. Then you can write a function that requires the wrapper using:
Copy code
fun <T> …()… where T : Ext, T : Additional = …
However that only really works if the external object has an interface or abstract class, it doesn't work for concrete classes
a
True, sadly that does not work with data classes as external code.
j
It's a neat idea, but I think lowering it to JVM would be nightmarish.
c
I don't see what the difficult part would be. It's essentially what is implemented when
@JvmInline value class
implements an interface.
j
What do you get as a JVM object when you cast the object to the interface type?
c
I'd say wrapper type, just like with value class