{"id":18894302,"url":"https://github.com/derive4j/hkt","last_synced_at":"2025-04-15T00:32:03.692Z","repository":{"id":57741851,"uuid":"54602896","full_name":"derive4j/hkt","owner":"derive4j","description":"Higher Kinded Type machinery for Java","archived":false,"fork":false,"pushed_at":"2022-02-28T12:03:19.000Z","size":210,"stargazers_count":82,"open_issues_count":10,"forks_count":9,"subscribers_count":9,"default_branch":"master","last_synced_at":"2025-03-22T07:55:34.415Z","etag":null,"topics":["annotation-processor","functional-programming","hk-encoding","hkt","java-8","typechecker"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/derive4j.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}},"created_at":"2016-03-24T00:40:16.000Z","updated_at":"2024-11-09T17:35:40.000Z","dependencies_parsed_at":"2022-09-10T22:31:56.352Z","dependency_job_id":null,"html_url":"https://github.com/derive4j/hkt","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derive4j%2Fhkt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derive4j%2Fhkt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derive4j%2Fhkt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derive4j%2Fhkt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/derive4j","download_url":"https://codeload.github.com/derive4j/hkt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248984426,"owners_count":21193750,"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":["annotation-processor","functional-programming","hk-encoding","hkt","java-8","typechecker"],"created_at":"2024-11-08T08:20:39.932Z","updated_at":"2025-04-15T00:32:01.802Z","avatar_url":"https://github.com/derive4j.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Higher Kinded Type machinery for Java\n\n[![Gitter](https://badges.gitter.im/derive4j/hkt.svg)](https://gitter.im/derive4j/hkt)\n[![Maven Central](https://img.shields.io/maven-central/v/org.derive4j.hkt/hkt.svg)][search.maven]\n[![Travis](https://travis-ci.org/derive4j/hkt.svg?branch=master)](https://travis-ci.org/derive4j/hkt)\n\nThis project provides type-safety for the higher kinded type encoding demonstrated in https://github.com/highj/highj via a JSR269 annotation processor.\n\nFor some theorical explanation of the encoding you may refer to the [Lightweight higher-kinded polymorphism](https://www.cl.cam.ac.uk/~jdy22/papers/lightweight-higher-kinded-polymorphism.pdf) paper.\n\n# Usage\n\n## Choose your HK encoding:\n\nthe two basic possibilities are:\n```java\nclass HkTest\u003cA\u003e implements __\u003cHkTest\u003c?\u003e, A\u003e {...}\n```\nand\n```java\nclass HkTest\u003cA\u003e implements __\u003cHkTest.w, A\u003e {\n  enum w { // could be any name, also could be a static nested class.\n  }\n}\n```\nWe say that `__\u003cHkTest.w, A\u003e` is the HK encoding of HkTest\u003cA\u003e and call `w` the *witness type* of `HkTest`.\n\n## What about binary type constructors ? Ternary ? And more ?\n\n@derive4j/hkt supplies interfaces `__\u003cf, A\u003e`, `__2\u003cf, A, B\u003e` up to `__9\u003cf, A, B, C, D, E, F, G, H, I\u003e`.\n\nFor example, a disjoint union type commonly called \"Either\" could be declared this way :\n```java\nclass Either\u003cA, B\u003e implements __2\u003cEither.µ, A, B\u003e {\n  enum µ {}\n  ...\n}\n```\n\n## Obligatory Monad example:\nThe higher kinded polymorphism gained by the encoding allows us to express things that are normally inexpressible in Java. Eg.:\n```java\npublic interface Monad\u003cm\u003e {\n  \u003cA\u003e __\u003cm, A\u003e pure(A a);\n\n  \u003cA, B\u003e __\u003cm, B\u003e bind(__\u003cm, A\u003e ma, Function\u003cA, __\u003cm, B\u003e\u003e f);\n\n  default \u003cA, B\u003e __\u003cm, B\u003e map(__\u003cm, A\u003e ma, Function\u003cA, B\u003e f) {\n    return bind(ma, f.andThen(this::pure));\n  }\n}\n```\n\n## Aliases interfaces\nYou may want to create aliases of derive4j hkt `__*` interfaces that better suit your naming preferences, maybe also adding\nsome default methods. Eg.:\n\n```java\ninterface HigherKind1\u003cTC extends HigherKind1\u003cTC, ?\u003e, T\u003e extends __\u003cTC, T\u003e {\n  default \u003cR\u003e R transform(Function\u003c__\u003cTC, T\u003e, R\u003e f) {\n    return f.apply(this);\n  }\n}\n```\nAnd so your hk-encoded classes would look like:\n```java\nclass HkTest\u003cA\u003e implements HigherKind1\u003cHkTest\u003c?\u003e, A\u003e {...}\n```\nIn any case, just try: if you do something wrong the annotation processor shall help you!\n\n## A note on safety : do not cast! Use the generated safe cast methods\nBy default the annotation processor will generate a `Hkt` class in each package that contains hk-encoded classes.\n\nThe generated class contains casting methods and factories of [TypeEq](src/main/java/org/derive4j/hkt/TypeEq.java) that allow you to safely recover the original type from its hk-encoding.\n\nHere is an example :\n\n- given the HKT types\n```java\nclass Maybe\u003cA\u003e implements __\u003cMaybe.µ, A\u003e {...}\n```\nand\n```java\nclass List\u003cA\u003e implements __\u003cList.µ, A\u003e {...}\n```\nboth in package `myorg.data`\n\n- then the following class will be generated\n```java\npackage myorg.data;\n\nfinal class Hkt {\n  private Hkt() {}\n  \n  static \u003cA\u003e Maybe\u003cA\u003e asMaybe(final __\u003cMaybe.µ, A\u003e hkt) {\n    return (Maybe\u003cA\u003e) hkt;\n  }\n  \n  static \u003cA\u003e List\u003cA\u003e asList(final __\u003cList.µ, A\u003e hkt) {\n    return (List\u003cA\u003e) hkt;\n  }\n}\n```\n\nNow you may ask : why is that safe ? I could implement `__\u003cMaybe.µ, A\u003e` in my `Foo\u003cA\u003e` class, pass an instance of it to `Hkt.asMaybe` and then boom !\n\nAnd to this the answer is no, you can't. That's the whole point of the hkt processor : would you try to implement `__\u003cMaybe.µ, A\u003e` in any other class than `Maybe`, you'd get a **compile time** error.\n\nThe processor thus ensures that the only possible implementation of `__\u003cMaybe.µ, A\u003e` is `Maybe\u003cA\u003e` : hence the safety of the cast in the generated methods.\n\n## Configuration of code generation\n\nCode generation can be customized by using the [HktConfig](src/main/java/org/derive4j/hkt/HktConfig.java) annotation (on\npackage-info or classes).\n\nConsider the example of the previous section : we would like the generated methods to be called `toX` instead of `asX`. Easy ! Just declare, in the `myorg.data` package, a `package-info` file as such :\n```java\n@HktConfig(coerceMethodName = \"to{ClassName}\")\npackage myorg.data;\n```\n\nNote that configuration is handled hierarchically through packages, classes and inner classes. That means that would you want to keep your `toX` methods and at the same time have the one for `List` generated in its own class, you could declare a `package-info` as afore mentionned and then annotate the `List` class this way:\n```java\n@HktConfig(generateIn = \"MyHktList\")\nclass List\u003cA\u003e implements __\u003cList.µ, A\u003e {...}\n```\nAs expected, the following two files would then be generated :\n```java\npackage myorg.data;\n\nfinal class Hkt {\n  private Hkt() {}\n  \n  static \u003cA\u003e Maybe\u003cA\u003e toMaybe(final __\u003cMaybe.µ, A\u003e hkt) {\n    return (Maybe\u003cA\u003e) hkt;\n  }\n}\n```\nand\n```java\npackage myorg.data;\n\nfinal class MyHktList {\n  private MyHktList() {}\n  \n  static \u003cA\u003e List\u003cA\u003e toList(final __\u003cList.µ, A\u003e hkt) {\n    return (List\u003cA\u003e) hkt;\n  }\n}\n```\n\n## I want it !\n\n### Maven\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003eorg.derive4j.hkt\u003c/groupId\u003e\n  \u003cartifactId\u003ehkt\u003c/artifactId\u003e\n  \u003cversion\u003e0.9.2\u003c/version\u003e\n\u003c/dependency\u003e\n```\n[search.maven]: http://search.maven.org/#search|ga|1|org.derive4j.hkt\n\n### Gradle\n```\ncompile(group: 'org.derive4j.hkt', name: 'hkt', version: '0.9.2', ext: 'jar')\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fderive4j%2Fhkt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fderive4j%2Fhkt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fderive4j%2Fhkt/lists"}