{"id":22541224,"url":"https://github.com/augustjune/context-applied","last_synced_at":"2025-10-16T21:32:03.929Z","repository":{"id":56415894,"uuid":"228594024","full_name":"augustjune/context-applied","owner":"augustjune","description":"Compiler plugin for intuitive tagless final","archived":false,"fork":false,"pushed_at":"2024-07-30T08:05:35.000Z","size":47,"stargazers_count":126,"open_issues_count":9,"forks_count":8,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-01-26T03:03:49.814Z","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/augustjune.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2019-12-17T10:41:44.000Z","updated_at":"2024-12-26T11:29:17.000Z","dependencies_parsed_at":"2024-12-28T20:11:51.093Z","dependency_job_id":null,"html_url":"https://github.com/augustjune/context-applied","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/augustjune%2Fcontext-applied","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/augustjune%2Fcontext-applied/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/augustjune%2Fcontext-applied/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/augustjune%2Fcontext-applied/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/augustjune","download_url":"https://codeload.github.com/augustjune/context-applied/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236748974,"owners_count":19198619,"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","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-12-07T12:14:56.131Z","updated_at":"2025-10-16T21:31:58.571Z","avatar_url":"https://github.com/augustjune.png","language":"Scala","readme":"context-applied\n=============\n\n[![Build Status](https://travis-ci.com/augustjune/context-applied.svg?branch=master)](https://travis-ci.com/augustjune/context-applied)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.augustjune/context-applied_2.13/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.augustjune/context-applied_2.13)\n\n### Overview\n**context-applied** is a Scala compiler plugin that gives you a handle to the value \nthat has the abilities specified by type parameter context bounds. \n\nExample: \n```scala\ndef fn[F[_]: Monad]: F[Int] = F.pure(12)\n``` \n\nThis scales across multiple contexts as well as multiple type parameters:\n```scala\ndef fn[F[_]: Applicative: Traverse, G[_]: Applicative]: G[F[Int]] = \n  F.traverse(F.pure(\"\"))(s =\u003e G.pure(s.size))\n```\n\n*This doesn't require any type class specific syntax nor \"summoner\" method*.\n\nIn fact it is achieved by introducing implicit conversions to the \nappropriate value from the implicit scope. \n\nRoughly speaking, you can pretend like you have a value named after the type parameter \nof the type that combines specified contexts: \n```scala\ndef fn[A: B: C: D] = {\n  val A: B[A] with C[A] with D[A] = ???\n\n// In reality A can be either B[A] or C[A] or D[A] in a particular moment\n}\n```\n\n### Usage\nPlugin is available for Scala 2.11, 2.12 and 2.13.\n```scala\naddCompilerPlugin(\"org.augustjune\" %% \"context-applied\" % \"0.1.4\")\n```\n\n### Use cases\n1. **Custom algebras.**\n    ```scala\n    trait Console[F[_]] {\n      def read: F[String]\n      \n      def write(s: String): F[Unit]\n    }\n    \n    def reply[F[_]: Console: FlatMap]: F[String] =\n      for {\n        s \u003c- F.read\n        _ \u003c- F.write(s)\n      } yield s\n    ```\n\n1. **Non-linear type class hierarchy.** \n\n    If you specify two algebras that derive from the same parent, \n    because of ambiguity you cannot use that parent's syntax.\n    Typical example of this problem is `Monad` and `Traverse` from *cats* \n    since they are both subtypes of `Functor`.\n    ```scala\n     import cats.syntax.all._\n     def fn[F[_]: Monad: Traverse](fs: F[String]) = \n       fs.map(_.size) // Compiler error\n     ```\n    With **context-applied** the first context that has *map* method\n    in function's context bounds is used.\n    ```scala\n    def fn[F[_]: Monad: Traverse](fs: F[String]) = \n       F.map(fs)(_.size)  // Monad's map is used\n    ```\n\n### Supported features\n1. Kind-projector support.\n   ```scala\n   def fn[F[_]: ApplicativeError[*[_], Throwable]]: F[Nothing] = \n     F.raiseError(new RuntimeException)\n   ```\n1. Type parameters of any kinds. \n    ```scala\n    def fn[F[_]: Applicative, B[_, _]: Bifunctor, A: Monoid] = {\n      val fa: F[A] = F.pure(A.empty)\n      val rf: Functor[B[A, *]] = B.rightFunctor[A]\n    }\n    ```\n1. Nested scopes.\n\n    Syntax is available for any context bounds: in classes, methods and nested methods.\n    ```scala\n    class Foo[F[_]: Applicative] {\n   \n      def bar[A: Monoid] = {\n        def baz[G[_]: Functor](ga: G[A]) = \n          G.map(ga)(F.pure)\n          \n        baz(List(A.empty))\n      }\n    }\n    ```\n \n### Special cases\nSince **context-applied** introduces additional syntax to your program \nit is important not to break any existing code or change its meaning.\nFor this reason there are cases when the plugin \njust gracefully skips parts of the program.\nIt happens when:\n\n1. Name of type parameter is already taken.\n    ```scala\n    class Foo[F[_]: Functor] {\n      val F: Int = 12                  // F: Functor[F] will not be introduced inside Foo \n      def f1[A: Monoid](A: Int) = ()   // A: Monoid[A] will not be introduced inside f1\n      def f2[F[_]: Monad] = ???        // F: Monad[F] will be available inside f2 as local value\n    }\n    ```\n1. Inside value classes.\n    ```scala\n    class Foo(val dummy: Boolean) extends AnyVal {\n      def fn[F[_]: Monad] = ???        // F: Monad[F] will not be introduced inside fn\n    }\n    ```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faugustjune%2Fcontext-applied","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faugustjune%2Fcontext-applied","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faugustjune%2Fcontext-applied/lists"}