Type Classes in Kotlin?

Does Kotlin support type classes in any way? If so, can someone point me to an example? Thanks!

2 Likes

Kotlin doesnot support type classes at the moment. In fact, there's no clear plan regarding this, in particular, type classes will not be supported in the version 1

Thanks for clarifying. Although I do enjoy type classes in Scala, they are a little obscure in the implementation and I would hope that Kotlin makes it easier if it implements them. In any event, type classes are the last chapter in Atomic Scala so it's easy to leave them off.

FYI, I just posted a few thoughts on this topic:

There is now a KEEP for type classes for those of you interested Compile-time Extension Interfaces by raulraja · Pull Request #87 · Kotlin/KEEP · GitHub

1 Like

Sorry for the thread necromancy, but I’m spitballing an idea in this general area, and would like to get some sanity check and feedback. Typeclasses become only really useful when you can also use higher kinded types, which are not supported in Kotlin. So, I think the only way forward to make this kind of work is code generation.

In the past, I put some effort into a typeclass library for Java called highJ, but I think it wouldn’t make much sense to translate it to Kotlin. Arrow-kt and similar existing “functional” libraries don’t provide support for something similar. With a well designed typeclass code generator library, it would be easy to create rich typeclass infrastructure like in Haskell, with monads, monad transformers, optics etc., and this is how I imagine it:

Say, we want to implement the Monad typeclass for existing types in Kotlin. First, we could have a template interface, which is just a placeholder for the monadic class:

interface Monadic<T>

Now, we write an interface that looks like the code we would like to generate, and indicate that it uses Monadic as place holder. We can have abstract methods (which must be provided) and concrete methods, which will be added to the generated monad typeclass:

@Typeclass(hktTemplates = [Monadic::class])
interface Monad {

    fun <A> pure(value: A): Monadic<A>

    fun <A, B> Monadic<A>.bind(transform: (A) -> Monadic<B>): Monadic<B>

    fun <A, B> Monadic<A>.fmap(transform: (A) -> B): Monadic<B> =
        bind { pure(transform(it)) }
}

Now, we can provide the necessary methods for a concrete class, and refer back to the typeclass:

@Instance(
    typeclass = Monad::class, 
    hkts = [List::class], 
    instanceName = "ListMonad"
)
interface ListMonadBase {
    fun <A> pure(value: A): List<A> = listOf(value)

    fun <A, B> List<A>.bind(transform: (A) -> List<B>): List<B> =
        flatMap(transform)
}

With that, KSP should have all necessary information to generate a ListMonad, like this:

@Generated
object ListMonad: ListMonadBase {
    fun <A, B> List<A>.fmap(transform: (A) -> B) = 
        bind { pure(transform(it)) }
}

Of course, this looks like a lot of boilerplate in this toy example, and the generation is inherently brittle towards code changes. But on the other hand, you can have many instances with a guaranteed structure and many generated functions.

Also note that inheritence is automatically supported, e.g. you could extend typeclass templates to build whole hierarchies, e.g.:

@Typeclass(hktTemplates = [Monadic::class])
interface MonadPlus : Monad {
    
    fun <A> mzero() : Monadic<A>
    
    infix fun <A> Monadic<A>.mplus(that: Monadic<A>): Monadic<A>
}

@Instance(
    typeclass = MonadPlus::class, 
    hkts = [List::class], 
    instanceName = "ListMonadPlus"
)
interface ListMonadPlusBase: ListMonadBase {
    fun <A> mzero() = emptyList<A>()

    infix fun <A> List<A>.mplus(that: List<A>): List<A> = this + that
}

What do you think of this idea?

1 Like