
Compiler-plugin stack enabling typeclass-oriented programming via context parameters; implicit evidence search, rule-style instances, derived instances, proof materialization, and Gradle/IDE integration.
kotlin-typeclasses is a K2 compiler-plugin stack for typeclass-oriented programming in Kotlin with context parameters.
This is a complete JVM application for the current documented release line.
// settings.gradle.kts
pluginManagement {
repositories {
gradlePluginPortal()
mavenCentral()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
}
}
rootProject.name = "typeclass-quickstart"// build.gradle.kts
plugins {
kotlin("jvm") version "2.3.10"
application
id("one.wabbit.typeclass") version "0.1.0"
}
dependencies {
implementation("one.wabbit:kotlin-typeclasses:0.1.0")
}
kotlin {
jvmToolchain(21)
}
application {
mainClass = "demo.MainKt"
}Then add src/main/kotlin/demo/Main.kt:
package demo
import one.wabbit.typeclass.Instance
import one.wabbit.typeclass.Typeclass
import one.wabbit.typeclass.summon
@Typeclass
interface Show<A> {
fun show(value: A): String
}
@Instance
object IntShow : Show<Int> {
override fun show(value: Int): String = value.toString()
}
@Instance
context(left: Show<A>, right: Show<B>)
fun <A, B> pairShow(): Show<Pair<A, B>> =
object : Show<Pair<A, B>> {
override fun show(value: Pair<A, B>): String =
"(" + left.show(value.first) + ", " + right.show(value.second) + ")"
}
context(_: Show<A>)
fun <A> render(value: A): String = summon<Show<A>>().show(value)
fun main() {
println(render(1 to 2))
}Run it:
./gradlew runExpected output:
(1, 2)
If you want to load the compiler plugin manually instead of using Gradle, add both -Xcontext-parameters and the compiler plugin artifact one.wabbit:kotlin-typeclasses-plugin:<baseVersion>-kotlin-<kotlinVersion>.
It combines:
summon(), derivation metadata, and proof APIsKotlin context parameters give the language a useful capability-passing syntax, but they do not by themselves provide a typeclass programming model.
kotlin-typeclasses adds the missing pieces:
@Typeclass
@Instance
Same, Subtype, KnownType, and TypeId
The goal is to make typeclass-style programming explicit and compile-time checked without forcing every call site to thread evidence manually.
This repository is experimental and pre-1.0.
supportedKotlinVersions in gradle.properties. At the moment that matrix is 2.3.10 and 2.4.0-Beta1.-Xcontext-parameters automatically.This project is trying to be powerful without becoming mystical.
| Module | Gradle project | Purpose |
|---|---|---|
library/ |
:kotlin-typeclasses |
Public runtime API: @Typeclass, @Instance, @Derive, summon(), derivation metadata, and builtin proof types |
compiler-plugin/ |
:kotlin-typeclasses-plugin |
K2 compiler plugin: discovery, resolution planning, FIR validation/refinement, and IR rewriting/codegen |
gradle-plugin/ |
:kotlin-typeclasses-gradle-plugin |
Gradle integration for one.wabbit.typeclass
|
ij-plugin/ |
:kotlin-typeclasses-ij-plugin |
IntelliJ IDEA integration for loading the compiler plugin into IDE analysis |
Most consumers need the runtime library and the Gradle plugin ID.
| Module | Coordinates or ID | Role |
|---|---|---|
| Runtime library | one.wabbit:kotlin-typeclasses:0.1.0 |
Annotations, summon(), derivation metadata, and proof APIs |
| Gradle plugin | plugin id one.wabbit.typeclass
|
Kotlin build integration and compiler-plugin wiring |
| Gradle plugin artifact | one.wabbit:kotlin-typeclasses-gradle-plugin:0.1.0 |
Published Gradle plugin implementation artifact |
| Compiler plugin |
one.wabbit:kotlin-typeclasses-plugin:0.1.0-kotlin-2.3.10 and one.wabbit:kotlin-typeclasses-plugin:0.1.0-kotlin-2.4.0-Beta1
|
Kotlin-line-specific K2 compiler plugin |
| IntelliJ plugin | one.wabbit:kotlin-typeclasses-ij-plugin:0.1.0 |
IDE helper plugin for external compiler-plugin loading |
Out of the box:
-Xcontext-parameters
@Typeclass
KClass<T> and KSerializer<T> evidence stay disabled unless you opt in through compiler-plugin optionscontext(...) parameters whose head is annotated with @Typeclass
@Instance declarations and associated companions@Derive, @DeriveVia, and @DeriveEquiv
Same, Subtype, KnownType, and TypeId
@DebugTypeclassResolution and the compiler trace optionThe important resolution rules are:
@Typeclass heads participate in implicit typeclass resolutionEquiv and by @DeriveVia only when the head is subclassable and has an accessible zero-argument constructor@Instance objects, functions, and immutable properties, plus associated companions@Instance declarations are restricted by file ownership: they must live with the typeclass head or one of the concrete provided classifiers in the targetFoo<A, B>, associated search includes the companion of Foo, companions of sealed supertypes of Foo, and companions of A and B plus their sealed supertypes@Derive(...) are part of the same search spaceSee the User Guide for the full user-facing model.
The compiler plugin is published per Kotlin compiler line because it depends on Kotlin compiler APIs.
Compiler-plugin coordinates use the form:
one.wabbit:kotlin-typeclasses-plugin:<baseVersion>-kotlin-<kotlinVersion>For this release train, the repository is configured to publish compiler-plugin variants for:
2.3.102.4.0-Beta1The Gradle plugin chooses the matching compiler-plugin artifact automatically. If you wire the compiler plugin directly, the -kotlin-<kotlinVersion> suffix must match the Kotlin compiler you are actually using.
If you are not using Gradle, wire the compiler plugin directly:
-Xcontext-parameters
-Xplugin=/path/to/kotlin-typeclasses-plugin.jar
-P plugin:one.wabbit.typeclass:builtinKClassTypeclass=disabled|enabled
-P plugin:one.wabbit.typeclass:builtinKSerializerTypeclass=disabled|enabled
-P plugin:one.wabbit.typeclass:typeclassTraceMode=inherit|disabled|failures|failures-and-alternatives|all|all-and-alternatives
If source code imports one.wabbit.typeclass.*, the runtime library still needs to be on the compilation classpath.
The IntelliJ plugin in this repository does not replace Kotlin analysis with a separate typeclass engine.
Its current job is narrower:
Enabling support here enables non-bundled K2 compiler plugins for the current trusted project session, not just kotlin-typeclasses.
These are important boundaries rather than hidden surprises:
For the current property-read limitation, see compiler-plugin/ISSUE_PROPERTIES.md.
@Derive, @DeriveVia, @DeriveEquiv, deriver contracts, and current boundariesKClass<T> / KSerializer<T> summoningCommon commands from the repo root:
./gradlew build
./gradlew :kotlin-typeclasses:jvmTest
./gradlew :kotlin-typeclasses-plugin:test
./gradlew :kotlin-typeclasses-gradle-plugin:test
./gradlew :kotlin-typeclasses-ij-plugin:testThe runtime project name is :kotlin-typeclasses, not :library.
LICENSE.md
legal/code-of-conduct/v1.0.0/CODE_OF_CONDUCT.md
legal/cla/v1.0.0/CLA.md
legal/contributor-privacy/v1.0.0/CONTRIBUTOR_PRIVACY.md
If you are new to the repository, this order works well:
kotlin-typeclasses is a K2 compiler-plugin stack for typeclass-oriented programming in Kotlin with context parameters.
This is a complete JVM application for the current documented release line.
// settings.gradle.kts
pluginManagement {
repositories {
gradlePluginPortal()
mavenCentral()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
}
}
rootProject.name = "typeclass-quickstart"// build.gradle.kts
plugins {
kotlin("jvm") version "2.3.10"
application
id("one.wabbit.typeclass") version "0.1.0"
}
dependencies {
implementation("one.wabbit:kotlin-typeclasses:0.1.0")
}
kotlin {
jvmToolchain(21)
}
application {
mainClass = "demo.MainKt"
}Then add src/main/kotlin/demo/Main.kt:
package demo
import one.wabbit.typeclass.Instance
import one.wabbit.typeclass.Typeclass
import one.wabbit.typeclass.summon
@Typeclass
interface Show<A> {
fun show(value: A): String
}
@Instance
object IntShow : Show<Int> {
override fun show(value: Int): String = value.toString()
}
@Instance
context(left: Show<A>, right: Show<B>)
fun <A, B> pairShow(): Show<Pair<A, B>> =
object : Show<Pair<A, B>> {
override fun show(value: Pair<A, B>): String =
"(" + left.show(value.first) + ", " + right.show(value.second) + ")"
}
context(_: Show<A>)
fun <A> render(value: A): String = summon<Show<A>>().show(value)
fun main() {
println(render(1 to 2))
}Run it:
./gradlew runExpected output:
(1, 2)
If you want to load the compiler plugin manually instead of using Gradle, add both -Xcontext-parameters and the compiler plugin artifact one.wabbit:kotlin-typeclasses-plugin:<baseVersion>-kotlin-<kotlinVersion>.
It combines:
summon(), derivation metadata, and proof APIsKotlin context parameters give the language a useful capability-passing syntax, but they do not by themselves provide a typeclass programming model.
kotlin-typeclasses adds the missing pieces:
@Typeclass
@Instance
Same, Subtype, KnownType, and TypeId
The goal is to make typeclass-style programming explicit and compile-time checked without forcing every call site to thread evidence manually.
This repository is experimental and pre-1.0.
supportedKotlinVersions in gradle.properties. At the moment that matrix is 2.3.10 and 2.4.0-Beta1.-Xcontext-parameters automatically.This project is trying to be powerful without becoming mystical.
| Module | Gradle project | Purpose |
|---|---|---|
library/ |
:kotlin-typeclasses |
Public runtime API: @Typeclass, @Instance, @Derive, summon(), derivation metadata, and builtin proof types |
compiler-plugin/ |
:kotlin-typeclasses-plugin |
K2 compiler plugin: discovery, resolution planning, FIR validation/refinement, and IR rewriting/codegen |
gradle-plugin/ |
:kotlin-typeclasses-gradle-plugin |
Gradle integration for one.wabbit.typeclass
|
ij-plugin/ |
:kotlin-typeclasses-ij-plugin |
IntelliJ IDEA integration for loading the compiler plugin into IDE analysis |
Most consumers need the runtime library and the Gradle plugin ID.
| Module | Coordinates or ID | Role |
|---|---|---|
| Runtime library | one.wabbit:kotlin-typeclasses:0.1.0 |
Annotations, summon(), derivation metadata, and proof APIs |
| Gradle plugin | plugin id one.wabbit.typeclass
|
Kotlin build integration and compiler-plugin wiring |
| Gradle plugin artifact | one.wabbit:kotlin-typeclasses-gradle-plugin:0.1.0 |
Published Gradle plugin implementation artifact |
| Compiler plugin |
one.wabbit:kotlin-typeclasses-plugin:0.1.0-kotlin-2.3.10 and one.wabbit:kotlin-typeclasses-plugin:0.1.0-kotlin-2.4.0-Beta1
|
Kotlin-line-specific K2 compiler plugin |
| IntelliJ plugin | one.wabbit:kotlin-typeclasses-ij-plugin:0.1.0 |
IDE helper plugin for external compiler-plugin loading |
Out of the box:
-Xcontext-parameters
@Typeclass
KClass<T> and KSerializer<T> evidence stay disabled unless you opt in through compiler-plugin optionscontext(...) parameters whose head is annotated with @Typeclass
@Instance declarations and associated companions@Derive, @DeriveVia, and @DeriveEquiv
Same, Subtype, KnownType, and TypeId
@DebugTypeclassResolution and the compiler trace optionThe important resolution rules are:
@Typeclass heads participate in implicit typeclass resolutionEquiv and by @DeriveVia only when the head is subclassable and has an accessible zero-argument constructor@Instance objects, functions, and immutable properties, plus associated companions@Instance declarations are restricted by file ownership: they must live with the typeclass head or one of the concrete provided classifiers in the targetFoo<A, B>, associated search includes the companion of Foo, companions of sealed supertypes of Foo, and companions of A and B plus their sealed supertypes@Derive(...) are part of the same search spaceSee the User Guide for the full user-facing model.
The compiler plugin is published per Kotlin compiler line because it depends on Kotlin compiler APIs.
Compiler-plugin coordinates use the form:
one.wabbit:kotlin-typeclasses-plugin:<baseVersion>-kotlin-<kotlinVersion>For this release train, the repository is configured to publish compiler-plugin variants for:
2.3.102.4.0-Beta1The Gradle plugin chooses the matching compiler-plugin artifact automatically. If you wire the compiler plugin directly, the -kotlin-<kotlinVersion> suffix must match the Kotlin compiler you are actually using.
If you are not using Gradle, wire the compiler plugin directly:
-Xcontext-parameters
-Xplugin=/path/to/kotlin-typeclasses-plugin.jar
-P plugin:one.wabbit.typeclass:builtinKClassTypeclass=disabled|enabled
-P plugin:one.wabbit.typeclass:builtinKSerializerTypeclass=disabled|enabled
-P plugin:one.wabbit.typeclass:typeclassTraceMode=inherit|disabled|failures|failures-and-alternatives|all|all-and-alternatives
If source code imports one.wabbit.typeclass.*, the runtime library still needs to be on the compilation classpath.
The IntelliJ plugin in this repository does not replace Kotlin analysis with a separate typeclass engine.
Its current job is narrower:
Enabling support here enables non-bundled K2 compiler plugins for the current trusted project session, not just kotlin-typeclasses.
These are important boundaries rather than hidden surprises:
For the current property-read limitation, see compiler-plugin/ISSUE_PROPERTIES.md.
@Derive, @DeriveVia, @DeriveEquiv, deriver contracts, and current boundariesKClass<T> / KSerializer<T> summoningCommon commands from the repo root:
./gradlew build
./gradlew :kotlin-typeclasses:jvmTest
./gradlew :kotlin-typeclasses-plugin:test
./gradlew :kotlin-typeclasses-gradle-plugin:test
./gradlew :kotlin-typeclasses-ij-plugin:testThe runtime project name is :kotlin-typeclasses, not :library.
LICENSE.md
legal/code-of-conduct/v1.0.0/CODE_OF_CONDUCT.md
legal/cla/v1.0.0/CLA.md
legal/contributor-privacy/v1.0.0/CONTRIBUTOR_PRIVACY.md
If you are new to the repository, this order works well: