Wow, arrow meta is a really powerful and amazing t...
# arrow-meta
d
Wow, arrow meta is a really powerful and amazing tool! It just cannot be underestimated! If you think about monads and stuff in a mathmeatical way, most of the functions involved arise from natural transformations, which should be implemented as static functions - just like Monad.return(): (T)->Monad<T>, or Monad.multilply(): Monad<Monad<<T>>->Monad<T>. Do you think it is possible to trick the kotlin compiler with some meta-plugin to accept something like """interface { @Companion fun ... }""" to implement "static interfaces"?
r
Hi @Dr. Florian Schmidt I think so and i’m not sure if you are asking about type classes or something similar which we have a way to do that with the Proofs plugin for simple cases. do you have a complete example of what you are trying to accomplish?
d
I want to do the following:
Copy code
annotation class Companion
annotation class OverrideCompanion

interface I {
    // I want this function to be implemented 
    // on the companion object of the 
    // implementing class
    @Companion 
    fun <S, T> f(s: S): T
}
class Impl : I {
    companion object {
        @OverrideCompanion
        fun <S, T> f(s: S): T = TODO()
    }
}
r
It’s possible to generate code as extension over existing companions. Adding companions automatically is not really recommended and there are types like List and others that you won’t be be able to do so and they don’t have a companion. For this particular pattern vanilla Kotlin already provides a way to do it which may look like:
Copy code
interface I {
  interface Companion {
    fun <S, T> f(s: S): T
  }
}
class Impl : I {
  companion object : I.Companion {
    override fun <S, T> f(s: S): T = TODO()
  }
}
you are trading two annotations and potentially confusing semantics to people not familiar with the plugin for a nested interface that contains the static functions you’d like the companion to implement.
y
To add to Raul's answer, you can force each subclass to provide some implementation of Companion like this: (playground)
Copy code
interface I {
  val companion: Companion
  interface Companion {
    fun <S: T, T> f(s: S): T
  }
}
class Impl : I {
  override val companion = Companion
  companion object : I.Companion {
    override fun <S: T, T> f(s: S): T = s
  }
}

fun main(){
    val i: I = Impl()
    println(i.companion.f("test"))
}
d
Hi @raulraja and @Youssef Shoaib [MOD] Thanks for your replies. It helped me a lot, because now, I do not need the annotations anymore. I will try the first approach and force implementation of the sub-interface via a plugin (or at least add IDE-support).
👍 1