kind-projector: writing type lambdas in Scala 2 without naming them
Compiler plugin for making type lambdas (type projections) easier to write
At a glance
- What is it?
- kind-projector is a Scala compiler plugin that rewrites type lambda syntax into ordinary Scala 2 type projections, so an anonymous partially applied type can be written inline. It is maintained for Scala 2 only, since Scala 3 has built-in type lambda syntax.
- Who is it for?
- kind-projector is worth adding to a Scala 2 codebase that leans on higher kinded types, where the alternative is naming every partially applied type or reaching for structural refinement syntax that no one enjoys reading. It is not worth adding to a new Scala 3 project, because Scala 3 has built-in type lambda syntax and the project itself states that no new features are being developed.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 25 days ago.
- What is it written in?
- Mainly Scala, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Type projections are the noise the plugin removes
The problem kind-projector addresses is a piece of Scala 2 syntactic noise that trips people up: using type projections to implement anonymous, partially applied types.
The canonical example contrasts a named type with the anonymous equivalent.
// partially-applied type named "IntOrA"
type IntOrA[A] = Either[Int, A]
// type projection implementing the same type anonymously (without a name).
({type L[A] = Either[Int, A]})#LThat second line is the thing you would write without the plugin. It works, it is valid Scala 2, and it is unpleasant to read, copy and maintain. The goal of the plugin is to add a syntax for type lambdas so the anonymous form can be written directly.
The audience is Scala developers working with higher kinded types. If your code deals with F-bounded polymorphism, type class abstraction over a container, or higher rank type parameters, this is the syntax that makes those types writable. If it does not, the plugin has nothing to offer you and adds a build dependency for no gain.
The library lives under the Typelevel organisation, which is the same group behind the wider Scala ecosystem tooling, and it is published to Maven Central under the org.typelevel organisation. The published artefact coordinates follow the pattern kind-projector_2.13.18, where the suffix is the full Scala version.
A tree transformation, not a parser change
The mechanism is worth understanding, because it explains both the convenience and the cost.
The plugin does not extend the Scala grammar. Instead it rewrites syntactically valid programs into new programs, which the documentation describes as letting us seem to add new keywords to the language. That is achieved through a compiler plugin performing an un-typed tree transformation.
The un-typed part is the key detail. The rewrite happens before type checking, on the syntax tree alone. That is what makes the plugin small and fast enough to sit in every compilation, and it is also why it cannot consult types to decide what to rewrite. The plugin has to decide from shape alone.
The consequence is stated directly in the documentation. One problem with this approach is that it changes the meaning of potentially valid programs. In practice that means you must avoid defining certain identifiers, and the list is explicit: Lambda and λ, then the star forms *, +* and -*, then Λ$, then the dollar suffixed Greek letters α$, β$ and so on.
So adopting the plugin is a naming reservation. A codebase that already defines a method or type named Lambda, or a type parameter called α$, will conflict. The documentation frames the decision in terms of whether you use lots of type lambdas and do not mind reserving those identifiers. If you do, this compiler plugin is for you.
Inline star syntax covers the common case only
The simplest syntax is the inline syntax, which resembles the way Scala uses _ to define anonymous functions like _ + _.
Underscore is already taken in Scala for existential types, and the documentation notes it is probably too late to change that syntax, so the plugin uses * for the same purpose, with +* and -* for covariant and contravariant type parameters.
Tuple2[*, Double] // equivalent to: type R[A] = Tuple2[A, Double]
Either[Int, +*] // equivalent to: type R[+A] = Either[Int, A]
Function2[-*, Long, +*] // equivalent to: type R[-A, +B] = Function2[A, Long, B]
EitherT[*[_], Int, *] // equivalent to: type R[F[_], B] = EitherT[F, Int, B]Read those equivalences carefully, because they show the real constraint. This syntax works when each type parameter in the type lambda is used in the body only once, and in the same order. The star is positional. The Function2 example works because A appears once and B appears once, in order.
That restriction is why the function syntax exists. For anything more complex, where a type parameter is used more than once or the order does not line up, the plugin offers a different form.
A second inline option arrived in version 0.13.0, which lets you use the _ symbol instead of the star. The idea is to roughly follow the proposed new syntax for wildcards and placeholders in Scala 3.2 and later, so a library can be cross compiled between Scala 2 and Scala 3 while writing the new Scala 3 syntax in both.
The mode is enabled with a compiler option, and in sbt that is a one line addition to scalacOptions:
ThisBuild / scalacOptions += "-P:kind-projector:underscore-placeholders"There is a hard warning attached. The mode is designed for scalac 2.12.14 and 2.13.6 and above, because those versions added the ability to use ? as the existential type wildcard, which frees the _ for reuse. Using the mode on older scalac versions, or without the -Xsource:3 flag, means losing the _ syntax entirely.
Function syntax handles lambdas the star cannot
The function syntax is described as the more powerful of the two, and it resembles anonymous functions like x => x + 1 or (x, y) => x + y.
For type lambdas, the entire function type is wrapped in a Lambda or λ type. The two names are equivalent, and the documentation notes that the former may be easier to type or say while the latter is less verbose.
Lambda[A => (A, A)] // equivalent to: type R[A] = (A, A)
Lambda[(A, B) => Either[B, A]] // equivalent to: type R[A, B] = Either[B, A]The difference from the star form is that the type parameters are bound explicitly on the left of the arrow, so each one can be referred to in the body more than once and the order does not have to match the order of appearance. That is exactly the case the inline syntax cannot express, which is why both forms exist rather than one replacing the other.
The identifier reservation is why the documentation offers the λ spelling as an alternative. If Lambda is already taken in your codebase, λ is a different identifier, and it also avoids the reserved name when the same code has to coexist with something else that defines Lambda.
Underneath, both forms end up in the same place, the type projection from the opening example. The plugin is a syntax layer over an existing Scala 2 feature, not a new type system.
Adding the plugin to sbt, Maven and Mill
The plugin supports Scala 2.11, 2.12 and 2.13, and since version 0.11.0 it is published against the full Scala version rather than the binary one, which the documentation attributes to issue 15.
For sbt, the build change is a single line in build.sbt:
addCompilerPlugin("org.typelevel" % "kind-projector" % "0.13.2" cross CrossVersion.full)The CrossVersion.full part is what selects the full version suffix, so the artefact resolves to kind-projector_2.13.x rather than a binary compatible one. The documentation also notes that in a multi-project build the addCompilerPlugin clause goes into the settings section for each sub-project, which is the kind of detail that bites people with a shared root build.
Maven users add it to the configuration of the maven-scala-plugin, using a suffixed artefact name such as kind-projector_2.13.6 in place of the plain artefact id, with the scala-maven-plugin needing the right _2.11.12, _2.12.15 or _2.13.6 form for the Scala version in use.
Mill users override scalacPluginIvyDeps, and the documentation highlights the triple colon form:
override def scalacPluginIvyDeps = Agg(
ivy"org.typelevel:::kind-projector:0.13.2"
)The triple colons ensure the full Scala version is used. The same warning applies across all three build tools: the full version suffix is not optional if you want the plugin to resolve.
One historical note: versions of the plugin earlier than 0.10.0 were released under a different organisation, org.spire-math, so a build that still references that group is on a much older line.
A maintenance notice that decides the question for most new projects
The maintenance note at the top of the documentation is short and decisive. The project is only maintained for Scala 2.x. No new features are developed, but bug fix releases will still be made available.
The reason given is that Dotty, which became Scala 3, has built-in type lambda syntax as well as kind-projector compatible syntax for wildcards. The language absorbed the feature.
That makes the decision for a new project straightforward. If you are starting on Scala 3, the language has the capability, there is no reason to add a compiler plugin, and the plugin will never gain the features that would make it worth the dependency. The _ placeholder mode described earlier is the interesting exception, since it exists precisely to let a library cross compile between Scala 2 and Scala 3 while writing the newer syntax in both.
Release history is consistent with a maintenance-only posture. v0.13.4 was released on 2025-09-30, v0.13.3 on 2024-02-23 and v0.13.2 on 2021-08-27, so roughly annual patch releases against a stable minor version. The last push was on 2026-09-28, so the tree is still being worked on even though the release line moves slowly.
The licence field on the repository says MIT, which is a permissive licence with no copyleft obligations. For a compiler plugin distributed through Maven Central and pulled into a build, that keeps the licensing surface small, though it is not legal advice.
The repository also carries a flake.nix and flake.lock for Nix based development environments, a build.sbt, a project/ directory for the build definition, scripts/, src/, a version.sbt and a COPYING file.
Editorial conclusion
kind-projector is worth adding to a Scala 2 codebase that leans on higher kinded types, where the alternative is naming every partially applied type or reaching for structural refinement syntax that no one enjoys reading. It is not worth adding to a new Scala 3 project, because Scala 3 has built-in type lambda syntax and the project itself states that no new features are being developed. Before adopting it, check the reserved identifiers listed in the documentation, since the plugin reserves Lambda, λ, the star forms and the dollar suffixed names, and confirm your build tool is set up for the full Scala version, because the plugin is published against CrossVersion.full.
Frequently asked questions
What does kind-projector do in Scala 2?
It is a compiler plugin that rewrites syntactically valid Scala 2 programs so that type lambda syntax can be used, replacing awkward type projections such as ({type L[A] = Either[Int, A]})#L. The rewrite is an un-typed tree transformation performed before type checking.
Which identifiers does kind-projector reserve?
Because the plugin rewrites programs before type checking, you must avoid defining Lambda and λ, the star forms *, +* and -*, Λ$, and the dollar suffixed Greek letters such as α$ and β$. The documentation says to use the plugin if you use lots of type lambdas and do not mind reserving those identifiers.
How do I add kind-projector to an sbt build?
Add addCompilerPlugin("org.typelevel" % "kind-projector" % "0.13.2" cross CrossVersion.full) to build.sbt, putting the clause into the settings section of each sub-project for a multi-project build. The full cross version is required so the plugin resolves against the complete Scala version.
Is kind-projector still worth using with Scala 3?
The project states it is only maintained for Scala 2.x, with no new features being developed, because Scala 3 has built-in type lambda syntax and kind-projector compatible wildcard syntax. The exception is the _ placeholder mode, which exists to support cross compilation between Scala 2 and Scala 3.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/typelevel-kind-projector)Was this useful?