{"id":16445379,"url":"https://github.com/lloydmeta/kontext","last_synced_at":"2025-02-26T09:46:19.964Z","repository":{"id":57717722,"uuid":"90633377","full_name":"lloydmeta/kontext","owner":"lloydmeta","description":"Like `implicitly` but for _all_ context-bound typeclass instances, automatically.","archived":false,"fork":false,"pushed_at":"2017-05-09T13:18:47.000Z","size":19,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-09T01:03:08.103Z","etag":null,"topics":["context-bounds","dsl","implicit","metaprogramming","scala","scalameta","tagless-final"],"latest_commit_sha":null,"homepage":null,"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/lloydmeta.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-05-08T13:49:25.000Z","updated_at":"2017-05-08T15:08:44.000Z","dependencies_parsed_at":"2022-09-10T23:12:48.903Z","dependency_job_id":null,"html_url":"https://github.com/lloydmeta/kontext","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lloydmeta%2Fkontext","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lloydmeta%2Fkontext/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lloydmeta%2Fkontext/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lloydmeta%2Fkontext/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lloydmeta","download_url":"https://codeload.github.com/lloydmeta/kontext/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240831200,"owners_count":19864711,"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":["context-bounds","dsl","implicit","metaprogramming","scala","scalameta","tagless-final"],"created_at":"2024-10-11T09:44:12.713Z","updated_at":"2025-02-26T09:46:19.741Z","avatar_url":"https://github.com/lloydmeta.png","language":"Scala","readme":"# kontext [![Build Status](https://travis-ci.org/lloydmeta/kontext.svg?branch=master)](https://travis-ci.org/lloydmeta/kontext) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.beachape/kontext_2.11/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.beachape/kontext_2.11) [![Scala.js](https://www.scala-js.org/assets/badges/scalajs-0.6.15.svg)](https://www.scala-js.org) [![Javadocs](https://www.javadoc.io/badge/com.beachape/kontext_2.12.svg)](https://www.javadoc.io/doc/com.beachape/kontext_2.12)\n\n\n`implicitly` but for _all_ context-bound typeclass instances, automatically.\n\nUseful when you have methods that are bound by lots of typeclasses and you don't want to maintain a long list of implicit parameters. Possibly useful when you want to do Tagless Final style EDSLs.\n\nWritten in [scala.meta](http://scalameta.org/) for future compatibility and other nice things (e.g. free IDE support, like in IntelliJ).\n\n## Why\n\nTurns this\n```scala\ndef cachedFib[F[_]](i: Int)(implicit Monad: Monad[F], KVStore: KVStore[F], Maths: Maths[F], Logger: Logger[F]): F[Int] = {\n  for {\n    cached \u003c- KVStore.get[Int](\"key\")\n    _      \u003c- Logger.info(\"on noes!\")\n  // etc\n}\n```\n\ninto\n\n```scala\n@boundly\ndef cachedFib[F[_]: Monad: KVStore: Maths: Logger](i: Int): F[Int] = {\n  for {\n    cached \u003c- KVStore.get[Int](\"key\")\n    _      \u003c- Logger.info(\"on noes!\")\n  // etc\n}\n```\n\nNot having to explicitly spell out names for your typeclass instances means less unneeded thinking (your typeclasses already have good enough names as is, right?) and no repetition of `[F]` means your code is more to the point. As a bonus, the typeclass constraints are still located in the front of your method signature, which acts as a visual cue as to what is needed to call the method (much like in Haskell).\n\n## Examples\n\n```scala\nimport kontext._\n\ntrait Maths[G[_]] {\n  def int(i: Int): G[Int]\n  def add(l: G[Int], r: G[Int]): G[Int]\n}\n\n// Simple usage\n@boundly\ndef add[F[_]: Maths](x: Int, y: Int) = Maths.add(Maths.int(x), Maths.int(y))\n\n// Example of renaming\n@boundly('Maths -\u003e 'M)\ndef addAliased[F[_]: Maths](x: Int, y: Int) = M.add(M.int(x), M.int(y))\n\n// Write an interpreter\ntype Id[A] = A\nimplicit val interpreter = new Maths[Id] {\n  def int(i: Int)                 = i\n  def add(l: Id[Int], r: Id[Int]) = l + r\n}\n\n// Use\nadd[Id](3, 10)\n// res0: Int = 13\n\naddAliased[Id](3, 10)\n// res1: Int = 13\n```\n\nFor a more realistic usage scenario, check out [examples/FibApp](https://github.com/lloydmeta/kontext/blob/master/examples/src/main/scala/FibApp.scala#L16), where 3 Tagless Final DSLs are mixed together.\n\n## Sbt\n\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.beachape/kontext_2.11/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.beachape/kontext_2.11)\n\n```scala\nlibraryDependencies += \"com.beachape\" %% \"kontext\" % s\"$latest_version\"\n\n\n// Additional ceremony for using Scalameta macro annotations\n\nresolvers += Resolver.url(\n  \"scalameta\",\n  url(\"http://dl.bintray.com/scalameta/maven\"))(Resolver.ivyStylePatterns)\n\n// A dependency on macro paradise is required to both write and expand\n// new-style macros.  This is similar to how it works for old-style macro\n// annotations and a dependency on macro paradise 2.x.\naddCompilerPlugin(\n  \"org.scalameta\" % \"paradise\" % \"3.0.0-M8\" cross CrossVersion.full)\n\nscalacOptions += \"-Xplugin-require:macroparadise\"\n\n```\n\n## How it works\n\nThe `@boundly` annotation simply injects values named after your typeclasses (and pointing to your typeclass instances) into the top of the method body.\n\n```scala\n@boundly\ndef add[F[_]: Maths](x: Int, y: Int) = Maths.add(Maths.int(x), Maths.int(y))\n\n// turns into \ndef add[F[_]: Maths](x: Int, y: Int) = {\n  val Maths = implicitly[Maths[F]]\n  Maths.add(Maths.int(x), Maths.int(y))\n}\n```\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flloydmeta%2Fkontext","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flloydmeta%2Fkontext","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flloydmeta%2Fkontext/lists"}