{"id":13682806,"url":"https://github.com/typelevel/kind-projector","last_synced_at":"2025-07-31T08:45:57.198Z","repository":{"id":2554556,"uuid":"3533170","full_name":"typelevel/kind-projector","owner":"typelevel","description":"Compiler plugin for making type lambdas (type projections) easier to write","archived":false,"fork":false,"pushed_at":"2025-07-28T15:35:50.000Z","size":411,"stargazers_count":926,"open_issues_count":10,"forks_count":75,"subscribers_count":27,"default_branch":"main","last_synced_at":"2025-07-30T18:37:58.696Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/typelevel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2012-02-24T05:55:56.000Z","updated_at":"2025-07-30T13:49:34.000Z","dependencies_parsed_at":"2023-09-24T09:04:12.057Z","dependency_job_id":"cd26e976-73c5-44e2-bd4e-f774a9ea9b3e","html_url":"https://github.com/typelevel/kind-projector","commit_stats":{"total_commits":395,"total_committers":55,"mean_commits":7.181818181818182,"dds":0.6683544303797468,"last_synced_commit":"8e6fa35d0de9c16d4c39a9533fd545d1ddd192cc"},"previous_names":["non/kind-projector"],"tags_count":36,"template":false,"template_full_name":null,"purl":"pkg:github/typelevel/kind-projector","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typelevel%2Fkind-projector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typelevel%2Fkind-projector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typelevel%2Fkind-projector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typelevel%2Fkind-projector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/typelevel","download_url":"https://codeload.github.com/typelevel/kind-projector/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/typelevel%2Fkind-projector/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267929189,"owners_count":24167443,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-30T02:00:09.044Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T13:01:53.551Z","updated_at":"2025-07-31T08:45:57.151Z","avatar_url":"https://github.com/typelevel.png","language":"Scala","funding_links":[],"categories":["Scala"],"sub_categories":[],"readme":"## Kind Projector\n\n![Continuous Integration](https://github.com/typelevel/kind-projector/workflows/Continuous%20Integration/badge.svg)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.typelevel/kind-projector_2.13.6/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.typelevel/kind-projector_2.13.6)\n\n### Note on maintenance\n\nThis project is only maintained for Scala 2.x. No new features are developed, but bug fix releases will still be made available. Dotty/Scala 3 has [built-in type lambda syntax](https://docs.scala-lang.org/scala3/reference/new-types/type-lambdas-spec.html) and [kind-projector compatible syntax](https://docs.scala-lang.org/scala3/reference/changed-features/wildcards.html).\n\n### Dedication\n\n\u003e \"But I don't want to go among mad people,\" Alice remarked.\n\u003e\n\u003e \"Oh, you can't help that,\" said the Cat: \"we're all mad here. I'm mad.\n\u003e You're mad.\"\n\u003e\n\u003e \"How do you know I'm mad?\" said Alice.\n\u003e\n\u003e \"You must be,\" said the Cat, \"or you wouldn't have come here.\"\n\u003e\n\u003e --Lewis Carroll, \"Alice's Adventures in Wonderland\"\n\n### Overview\n\nOne piece of Scala syntactic noise that often trips people up is the\nuse of type projections to implement anonymous, partially-applied\ntypes. For example:\n\n```scala\n// partially-applied type named \"IntOrA\"\ntype IntOrA[A] = Either[Int, A]\n\n// type projection implementing the same type anonymously (without a name).\n({type L[A] = Either[Int, A]})#L\n```\n\nMany people have wished for a better way to do this.\n\nThe goal of this plugin is to add a syntax for type lambdas. We do\nthis by rewriting syntactically valid programs into new programs,\nletting us seem to add new keywords to the language. This is achieved\nthrough a compiler plugin performing an (un-typed) tree\ntransformation.\n\nOne problem with this approach is that it changes the meaning of\n(potentially) valid programs. In practice this means that you must\navoid defining the following identifiers:\n\n 1. `Lambda` and `λ`\n 2. `*`, `+*`, and `-*`\n 4. `Λ$`\n 5. `α$`, `β$`, ...\n\nIf you find yourself using lots of type lambdas, and you don't mind\nreserving those identifiers, then this compiler plugin is for you!\n\n### Using the plugin\n\nKind-projector supports Scala 2.11, 2.12, and 2.13.\n\n_Note_: as of version 0.11.0 the plugin is published against the full Scala version\n(see #15)\n\nTo use this plugin in your own projects, add the following lines to\nyour `build.sbt` file:\n\n```scala\naddCompilerPlugin(\"org.typelevel\" % \"kind-projector\" % \"0.13.2\" cross CrossVersion.full)\n```\n_Note_: for multi-project builds - put `addCompilerPlugin` clause into settings section for each sub-project.\n\nFor maven projects, add the plugin to the configuration of the\nmaven-scala-plugin (remember to use `_2.11.12`, `_2.12.15`, `_2.13.6` etc as appropriate):\n\n    \u003cplugin\u003e\n      \u003cgroupId\u003enet.alchim31.maven\u003c/groupId\u003e\n      \u003cartifactId\u003escala-maven-plugin\u003c/artifactId\u003e\n      ...\n      \u003cconfiguration\u003e\n        \u003ccompilerPlugins\u003e\n          \u003ccompilerPlugin\u003e\n            \u003cgroupId\u003eorg.typelevel\u003c/groupId\u003e\n            \u003cartifactId\u003ekind-projector_2.13.6\u003c/artifactId\u003e\n            \u003cversion\u003e0.13.2\u003c/version\u003e\n          \u003c/compilerPlugin\u003e\n        \u003c/compilerPlugins\u003e\n      \u003c/configuration\u003e\n    \u003c/plugin\u003e\n\nFor mill projects, add the plugin to the `scalacPluginIvyDep`\nNote the triple colons (`:::`) to ensure it uses the full scala version.\n\n    override def scalacPluginIvyDeps = Agg(\n      ivy\"org.typelevel:::kind-projector:0.13.2\"\n    )\n\nThat's it!\n\nVersions of the plugin earlier than 0.10.0 were released under a\ndifferent organization (`org.spire-math`).\n\n### Inline Syntax\n\nThe simplest syntax to use is the inline syntax. This syntax resembles\nScala's use of underscores to define anonymous functions like `_ + _`.\n\nSince underscore is used for existential types in Scala (and it is\nprobably too late to change this syntax), we use `*` for the same\npurpose. We also use `+*` and `-*` to handle covariant and\ncontravariant types parameters.\n\nHere are a few examples:\n\n```scala\nTuple2[*, Double]        // equivalent to: type R[A] = Tuple2[A, Double]\nEither[Int, +*]          // equivalent to: type R[+A] = Either[Int, A]\nFunction2[-*, Long, +*]  // equivalent to: type R[-A, +B] = Function2[A, Long, B]\nEitherT[*[_], Int, *]    // equivalent to: type R[F[_], B] = EitherT[F, Int, B]\n```\n\nAs you can see, this syntax works when each type parameter in the type\nlambda is only used in the body once, and in the same order. For more\ncomplex type lambda expressions, you will need to use the function\nsyntax.\n\n#### Inline Underscore Syntax\n\nSince version `0.13.0` kind-projector adds an option to use underscore symbol `_` instead of `*` to define anonymous type lambdas.\nThe syntax roughly follows the [proposed new syntax for wildcards and placeholders](https://docs.scala-lang.org/scala3/reference/changed-features/wildcards.html#migration-strategy) for Scala 3.2+ and is designed to allow cross-compilation of libraries between Scala 2 and Scala 3 while using the new Scala 3 syntax for both versions.\n\nTo enable this mode, add `-P:kind-projector:underscore-placeholders` to your scalac command-line. In sbt you may do this as follows:\n\n```scala\nThisBuild / scalacOptions += \"-P:kind-projector:underscore-placeholders\"\n```\n\nThis mode is designed to be used with scalac versions `2.12.14`+ and `2.13.6`+, these versions add an the ability to use `?` as the existential type wildcard ([scala/scala#9560](https://github.com/scala/scala/pull/9560)), allowing to repurpose the underscore without losing the ability to write existential types. It is not advised that you use this mode with older versions of scalac or without `-Xsource:3` flag, since you will lose the underscore syntax entirely.\n\nHere are a few examples:\n\n```scala\nTuple2[_, Double]        // equivalent to: type R[A] = Tuple2[A, Double]\nEither[Int, +_]          // equivalent to: type R[+A] = Either[Int, A]\nFunction2[-_, Long, +_]  // equivalent to: type R[-A, +B] = Function2[A, Long, B]\nEitherT[_[_], Int, _]    // equivalent to: type R[F[_], B] = EitherT[F, Int, B]\n```\n\nExamples with `-Xsource:3`'s `?`-wildcard:\n\n```scala\nTuple2[_, ?]        // equivalent to: type R[A] = Tuple2[A, x] forSome { type x }\nEither[?, +_]          // equivalent to: type R[+A] = Either[x, A] forSome { type x }\nFunction2[-_, ?, +_]  // equivalent to: type R[-A, +B] = Function2[A, x, B] forSome { type x }\nEitherT[_[_], ?, _]    // equivalent to: type R[F[_], B] = EitherT[F, x, B] forSome { type x }\n```\n\n### Function Syntax\n\nThe more powerful syntax to use is the function syntax. This syntax\nresembles anonymous functions like `x =\u003e x + 1` or `(x, y) =\u003e x + y`.\nIn the case of type lambdas, we wrap the entire function type in a\n`Lambda` or `λ` type. Both names are equivalent: the former may be\neasier to type or say, and the latter is less verbose.\n\nHere are some examples:\n\n```scala\nLambda[A =\u003e (A, A)]              // equivalent to: type R[A] = (A, A)\nLambda[(A, B) =\u003e Either[B, A]]   // equivalent to: type R[A, B] = Either[B, A]\nLambda[A =\u003e Either[A, List[A]]]  // equivalent to: type R[A] = Either[A, List[A]]\n```\n\nSince types like `(+A, +B) =\u003e Either[A, B]` are not syntactically\nvalid, we provide two alternate methods to specify variance when using\nfunction syntax:\n\n * Plus/minus: `(+[A], +[B]) =\u003e Either[A, B]`\n * Backticks: ``(`+A`, `+B`) =\u003e Either[A, B]``\n\n(Note that unlike names like `*`, `+` and `-` do not have to be\nreserved. They will only be interpreted this way when used in\nparameters to `Lambda[...]` types, which should never conflict with\nother usage.)\n\nHere are some examples with variance:\n\n```scala\nλ[`-A` =\u003e Function1[A, Double]]          // equivalent to: type R[-A] = Function1[A, Double]\nλ[(-[A], +[B]) =\u003e Function2[A, Int, B]]  // equivalent to: type R[-A, +B] = Function2[A, Int, B]\nλ[`+A` =\u003e Either[List[A], List[A]]]      // equivalent to: type R[+A] = Either[List[A], List[A]]\n```\n\nThe function syntax also supports higher-kinded types as type\nparameters. The syntax overloads the existential syntax in this case\n(since the type parameters to a type lambda should never contain an\nexistential).\n\nHere are a few examples with higher-kinded types:\n\n```scala\nLambda[A[_] =\u003e List[A[Int]]]  // equivalent to: type R[A[_]] = List[A[Int]]\nLambda[(A, B[_]) =\u003e B[A]]     // equivalent to: type R[A, B[_]] = B[A]\n```\n\nFinally, variance annotations on higher-kinded sub-parameters are\nsupported using backticks:\n\n```scala\nLambda[`x[+_]` =\u003e Q[x, List] // equivalent to: type R[x[+_]] = Q[x, List]\nLambda[`f[-_, +_]` =\u003e B[f]   // equivalent to: type R[f[-_, +_]] = B[f]\n```\n\nThe function syntax with backtick type parameters is the most\nexpressive syntax kind-projector supports. The other syntaxes are\neasier to read at the cost of being unable to express certain\n(hopefully rare) type lambdas.\n\n### Type lambda gotchas\n\nThe inline syntax is the tersest and is often preferable when\npossible. However, there are some type lambdas which it cannot\nexpress.\n\nFor example, imagine that we have `trait Functor[F[_]]`.\n\nYou might want to write `Functor[Future[List[*]]]`, expecting to get\nsomething like:\n\n```scala\ntype X[a] = Future[List[a]]\nFunctor[X]\n```\n\nHowever, `*` always binds at the tightest level, meaning that\n`List[*]` is interpreted as `type X[a] = List[a]`, and that\n`Future[List[*]]` is invalid.\n\nIn these cases you should prefer the lambda syntax, which would be\nwritten as:\n\n```scala\nFunctor[Lambda[a =\u003e Future[List[a]]]]\n```\n\nOther types which cannot be written correctly using inline syntax are:\n\n * `Lambda[a =\u003e (a, a)]` (repeated use of `a`).\n * `Lambda[(a, b) =\u003e Either[b, a]]` (reverse order of type params).\n * `Lambda[(a, b) =\u003e Function1[a, Option[b]]]` (similar to example).\n\n(And of course, you can use `λ[...]` instead of `Lambda[...]` in any\nof these expressions.)\n\n### Under The Hood\n\nThis section shows the exact code produced for a few type lambda\nexpressions.\n\n```scala\nEither[Int, *]\n({type Λ$[β$0$] = Either[Int, β$0$]})#Λ$\n\nFunction2[-*, String, +*]\n({type Λ$[-α$0$, +γ$0$] = Function2[α$0$, String, γ$0$]})#Λ$\n\nLambda[A =\u003e (A, A)]\n({type Λ$[A] = (A, A)})#Λ$\n\nLambda[(`+A`, B) =\u003e Either[A, Option[B]]]\n({type Λ$[+A, B] = Either[A, Option[B]]})#Λ$\n\nLambda[(A, B[_]) =\u003e B[A]]\n({type Λ$[A, B[_]] = B[A]})#Λ$\n```\n\nAs you can see, names like `Λ$` and `α$` are forbidden because they\nmight conflict with names the plugin generates.\n\nIf you dislike these unicode names, pass `-Dkp:genAsciiNames=true` to\nscalac to use munged ASCII names. This will use `L_kp` in place of\n`Λ$`, `X_kp0$` in place of `α$`, and so on.\n\n### Polymorphic lambda values\n\nScala does not have built-in syntax or types for anonymous function\nvalues which are polymorphic (i.e. which can be parameterized with\ntypes). To illustrate that consider both of these methods:\n\n```scala\ndef firstInt(xs: List[Int]): Option[Int] = xs.headOption\ndef firstGeneric[A](xs: List[A]): Option[A] = xs.headOption\n```\n\nHaving implemented these methods, we can see that the second just\ngeneralizes the first to work with any type: the function bodies are\nidentical. We'd like to be able to rewrite each of these methods as a\nfunction value, but we can only represent the first method\n(`firstInt`) this way:\n\n```scala\nval firstInt0: List[Int] =\u003e Option[Int] = _.headOption\nval firstGeneric0 \u003cwhat to put here???\u003e\n```\n\n(One reason to want to do this rewrite is that we might have a method\nlike `.map` which we'd like to pass an anonymous function value.)\n\nSeveral libraries define their own polymorphic function types, such as\nthe following polymorphic version of `Function1` (which we can use to\nimplement `firstGeneric0`):\n\n```scala\ntrait PolyFunction1[-F[_], +G[_]] {\n  def apply[A](fa: F[A]): G[A]\n}\n\nval firstGeneric0: PolyFunction1[List, Option] =\n  new PolyFunction1[List, Option] {\n    def apply[A](xs: List[A]): Option[A] = xs.headOption\n  }\n```\n\nIt's nice that `PolyFunction1` enables us to express polymorphic\nfunction values, but at the level of syntax it's not clear that we've\nsaved much over defining a polymorphic method (i.e. `firstGeneric`).\n\nSince 0.9.0, Kind-projector provides a value-level rewrite to fix this\nissue and make polymorphic functions (and other types that share their\ngeneral shape) easier to work with:\n\n```scala\nval firstGeneric0 = λ[PolyFunction1[List, Option]](_.headOption)\n```\n\nEither `λ` or `Lambda` can be used (in a value position) to trigger\nthis rewrite. By default, the rewrite assumes that the \"target method\"\nto define is called `apply` (as in the previous example), but a\ndifferent method can be selected via an explicit call.\n\nIn the following example we are using the polymorphic lambda syntax to\ndefine a `run` method on an instance of the `PF` trait:\n\n```scala\ntrait PF[-F[_], +G[_]] {\n  def run[A](fa: F[A]): G[A]\n}\n\nval f = Lambda[PF[List, Option]].run(_.headOption)\n```\n\nIt's possible to nest this syntax. Here's an example taken from\n[the wild](http://www.slideshare.net/timperrett/enterprise-algebras-scala-world-2016/49)\nof using nested polymorphic lambdas to remove boilerplate:\n\n```scala\n// without polymorphic lambdas, as in the slide\ndef injectFC[F[_], G[_]](implicit I: Inject[F, G]) =\n  new (FreeC[F, *] ~\u003e FreeC[G, *]) {\n    def apply[A](fa: FreeC[F, A]): FreeC[G, A] =\n      fa.mapSuspension[Coyoneda[G, *]](\n        new (Coyoneda[F, *] ~\u003e Coyoneda[G, *]) {\n          def apply[B](fb: Coyoneda[F, B]): Coyoneda[G, B] = fb.trans(I)\n        }\n      )\n  }\n\n// with polymorphic lambdas\ndef injectFC[F[_], G[_]](implicit I: Inject[F, G]) =\n  λ[FreeC[F, *] ~\u003e FreeC[G, *]](\n    _.mapSuspension(λ[Coyoneda[F, *] ~\u003e Coyoneda[G, *]](_.trans(I)))\n  )\n```\n\nKind-projector's support for type lambdas operates at the *type level*\n(in type positions), whereas this feature operates at the *value\nlevel* (in value positions). To avoid reserving too many names the `λ`\nand `Lambda` names were overloaded to do both (mirroring the\nrelationship between types and their companion objects).\n\nHere are some examples of expressions, along with whether the lambda\nsymbol involved represents a type (traditional type lambda) or a value\n(polymorphic lambda):\n\n```scala\n// type lambda (type level)\nval functor: Functor[λ[a =\u003e Either[Int, a]]] = implicitly\n\n// polymorphic lambda (value level)\nval f = λ[Vector ~\u003e List](_.toList)\n\n// type lambda (type level)\ntrait CF2 extends Contravariant[λ[a =\u003e Function2[a, a, Double]]] {\n  ...\n}\n\n// polymorphic lambda (value level)\nxyz.translate(λ[F ~\u003e G](fx =\u003e fx.flatMap(g)))\n```\n\nOne pattern you might notice is that when `λ` occurs immediately\nwithin `[]` it is referring to a type lambda (since `[]` signals a\ntype application), whereas when it occurs after `=` or within `()` it\nusually refers to a polymorphic lambda, since those tokens usually\nsignal a value. (The `()` syntax for tuple and function types is an\nexception to this pattern.)\n\nThe bottom line is that if you could replace a λ-expression with a\ntype constructor, it's a type lambda, and if you could replace it with\na value (e.g. `new Xyz[...] { ... }`) then it's a polymorphic lambda.\n\n### Polymorphic lambdas under the hood\n\nWhat follows are the gory details of the polymorphic lambda rewrite.\n\nPolymorphic lambdas are a syntactic transformation that occurs just\nafter parsing (before name resolution or typechecking). Your code will\nbe typechecked *after* the rewrite.\n\nWritten in its most explicit form, a polymorphic lambda looks like\nthis:\n\n```scala\nλ[Op[F, G]].someMethod(\u003cexpr\u003e)\n```\n\nand is rewritten into something like this:\n\n```scala\nnew Op[F, G] {\n  def someMethod[A](x: F[A]): G[A] = \u003cexpr\u003e(x)\n}\n```\n\n(The names `A` and `x` are used for clarity –- in practice unique\nnames will be used for both.)\n\nThis rewrite requires that the following are true:\n\n * `F` and `G` are unary type constructors (i.e. of shape `F[_]` and `G[_]`).\n * `\u003cexpr\u003e` is an expression of type `Function1[_, _]`.\n * `Op` is parameterized on two unary type constructors.\n * `someMethod` is parametric (for any type `A` it takes `F[A]` and returns `G[A]`).\n\nFor example, `Op` might be defined like this:\n\n```scala\ntrait Op[M[_], N[_]] {\n  def someMethod[A](x: M[A]): N[A]\n}\n```\n\nThe entire λ-expression will be rewritten immediately after parsing\n(and before name resolution or typechecking). If any of these\nconstraints are not met, then a compiler error will occur during a\nlater phase (likely type-checking).\n\nHere are some polymorphic lambdas along with the corresponding code\nafter the rewrite:\n\n```scala\nval f = Lambda[NaturalTransformation[Stream, List]](_.toList)\nval f = new NaturalTransformation[Stream, List] {\n  def apply[A](x: Stream[A]): List[A] = x.toList\n}\n\ntype Id[A] = A\nval g = λ[Id ~\u003e Option].run(x =\u003e Some(x))\nval g = new (Id ~\u003e Option) {\n  def run[A](x: Id[A]): Option[A] = Some(x)\n}\n\nval h = λ[Either[Unit, *] Convert Option](_.fold(_ =\u003e None, a =\u003e Some(a)))\nval h = new Convert[Either[Unit, *], Option] {\n  def apply[A](x: Either[Unit, A]): Option[A] =\n    x.fold(_ =\u003e None, a =\u003e Some(a))\n}\n\n// that last example also includes a type lambda.\n// the full expansion would be:\nval h = new Convert[({type Λ$[β$0$] = Either[Unit, β$0$]})#Λ$, Option] {\n  def apply[A](x: ({type Λ$[β$0$] = Either[Unit, β$0$]})#Λ$): Option[A] =\n    x.fold(_ =\u003e None, a =\u003e Some(a))\n}\n```\n\nUnfortunately the type errors produced by invalid polymorphic lambdas\nare likely to be difficult to read. This is an unavoidable consequence\nof doing this transformation at the syntactic level.\n\n### Building the plugin\n\nYou can build kind-projector using SBT 0.13.0 or newer.\n\nHere are some useful targets:\n\n * `compile`: compile the code\n * `package`: build the plugin jar\n * `test`: compile the test files (no tests run; compilation is the test)\n * `console`: launch a REPL with the plugin loaded so you can play around\n\nYou can use the plugin with `scalac` by specifying it on the\ncommand-line. For instance:\n\n```\nscalac -Xplugin:kind-projector_2.13.6-0.13.2.jar test.scala\n```\n\n### Releasing the plugin\n\nThis project must use full cross-versioning and thus needs to be\nrepublished for each new release of Scala, but if the code doesn't\nchange, we prefer not to ripple downstream with a version bump.  Thus,\nwe typically republish from a tag.\n\n1. Be sure you're on Java 8.\n\n2. Run `./scripts/back-publish` with the tag and Scala version\n\n   ```console\n   $ ./scripts/back-publish\n   Usage: ./scripts/back-publish [-t \u003ctag\u003e] [-s \u003cscala_version\u003e]\n   $ ./scripts/back-publish -t v0.13.2 -s 2.13.8\n   ```\n\nYou can also run the above steps in CI by manually triggering the\nworkflow in `backpublish.yml`. To do so, navigate to the **Actions**\ntab, select the **Back-Publish** workflow from the left side-bar, and\nclick **Run workflow** to access a drop-down menu to run the workflow.\n\n\u003cimg width=\"376\" alt=\"Screen Shot 2022-01-11 at 11 09 12\" src=\"https://user-images.githubusercontent.com/3119428/149005987-5643361f-bb76-4e3b-8347-69bb55fbed60.png\"\u003e\n\n### Known issues \u0026 errata\n\nWhen dealing with type parameters that take covariant or contravariant\ntype parameters, only the function syntax is supported. Huh???\n\nHere's an example that highlights this issue:\n\n```scala\ndef xyz[F[_[+_]]] = 12345\ntrait Q[A[+_], B[+_]]\n\n// we can use kind-projector to adapt Q for xyz\nxyz[λ[`x[+_]` =\u003e Q[x, List]] // ok\n\n// but these don't work (although support for the second form\n// could be added in a future release).\nxyz[Q[*[+_], List]]          // invalid syntax\nxyz[Q[*[`+_`], List]]        // unsupported\n```\n\nThere have been suggestions for better syntax, like\n`[A, B]Either[B, A]` or `[A, B] =\u003e Either[B, A]` instead of\n`Lambda[(A, B) =\u003e Either[B, A]]`.  Unfortunately this would actually\nrequire modifying the parser (i.e. the language itself) which is\noutside the scope of this project (at least, until there is an earlier\ncompiler phase to plug into).\n\nOthers have noted that it would be nicer to be able to use `_` for\ntypes the way we do for values, so that we could use `Either[Int, _]`\nto define a type lambda the way we use `3 + _` to define a\nfunction. Unfortunately, it's probably too late to modify the meaning\nof `_`, which is why we chose to use `*` instead.\n\n### Future Work\n\nAs of 0.5.3, kind-projector should be able to support any type lambda\nthat can be expressed via type projections, at least using the\nfunction syntax. If you come across a type for which kind-projector\nlacks a syntax, please report it.\n\n### Disclaimers\n\nKind projector is an unusual compiler plugin in that it runs *before*\nthe `typer` phase. This means that the rewrites and renaming we are\ndoing are relatively fragile, and the author disclaims all warranty or\nliability of any kind.\n\n(That said, there are currently no known bugs.)\n\nIf you are using kind-projector in one of your projects, please feel\nfree to get in touch to report problems (or a lack of problems)!\n\n### Community\n\nPeople are expected to follow the\n[Scala Code of Conduct](https://scala-lang.org/conduct/)\nwhen discussing Kind-projector on GitHub or other venues.\n\nThe project's current maintainers are:\n\n * [Erik Osheim](http://github.com/non)\n * [Tomas Mikula](http://github.com/tomasmikula)\n * [Seth Tisue](https://github.com/sethtisue)\n * [Miles Sabin](https://github.com/milessabin)\n\n### Copyright and License\n\nAll code is available to you under the MIT license, available at\nhttp://opensource.org/licenses/mit-license.php and also in the COPYING\nfile.\n\nCopyright Erik Osheim, 2011-2021.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftypelevel%2Fkind-projector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftypelevel%2Fkind-projector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftypelevel%2Fkind-projector/lists"}