A KEEP for Type Classes as a natural fit of the ex...
# language-proposals
r
A KEEP for Type Classes as a natural fit of the extension system Kotlin already provides https://github.com/Kotlin/KEEP/pull/87
👍 2
👍🏻 4
b
I like the idea, but why are its functions
static
by default? and what would a
static fun
in an
extension
do?
r
Copy code
extension Int : Monoid {
    fun Int.combine(b: Int): Int = this * b
    fun empty(): Int = 1
}
Here
combine(b: Int)
will be enabled as it is today on regular extension functions and provide
1.combine(2)
for example. It has the type prepended so it's the same as when you declare an extension function outside a typeclass. In the case of
empty()
since it has no type annotation it operates over the type itself enabling
Int.empty()
. Originally it was proposed that these are defined as
Int.Companion.empty
but not all classes have companions and we don't really need the companion for this feature. Typeclasses may simplify companions and deprecate the usage of
inline
reified
in many cases since the same can be accomplished in a much easier way and without restriction at call sites. Example of typeclasses replacing inline reified: https://github.com/Kotlin/KEEP/pull/87#issuecomment-333915196 Discussion about the companion syntax and how typeclasses can replace companions all together: https://github.com/Kotlin/KEEP/pull/87#issuecomment-333653188
c
@raulraja I don’t see anything in this proposal about higher kinded types, did I miss something?
r
@cedric At the end of the proposal there is a couple of examples where types are expressed in higher kind position :
Copy code
typeclass FunctionK<F<_>, G<_>> {
   fun <A> invoke(fa: F<A>): G<A>
}

extension Option2List : FunctionK<Option, List> {
   fun <A> invoke(fa: Option<A>): List<A> =
     fa.fold({ emptyList() }, { listOf(it) })
 }
I believe HKs in Kotlin will be trivial to implement since the compiler knows when a kind is in that position already. We are discussing now if we can adapt the above syntax to the extension style where you wouldn't have to name or require instances as args.
c
Oh missed that, thanks for pointing it out
I’m curious to hear what the team thinks of “Higher Kinds will be trivial to implement” 🙂
r
I think they are very hard to implement when you have dependent types in the lang since those mean projections but in this case where only kinds of arity 1 are supported is just a matter of ensuring call sites provide for generics the unapplied type. In this case
Option
. Kinds with more than one arity can always be partially applied if needed. For example:
Copy code
typealias EitherThrowable<A> = Either<Throwable, A>
Now
EitherThrowable
can be used in kind position if we don't want to support syntax like
F<_, _>
. In my latest comment at https://github.com/Kotlin/KEEP/pull/87#issuecomment-334262293 I'm proposing a variant that supports more complex typeclasses also as part of extensions with the kind of syntax @elizarov proposed originally to keep TC in the context of extensions without boilerplate at call sites.