An open API service indexing awesome lists of open source software.

https://github.com/garciat/java-type-classes

Haskell-like type class resolution for Java.
https://github.com/garciat/java-type-classes

haskell java typeclasses

Last synced: 19 days ago
JSON representation

Haskell-like type class resolution for Java.

Awesome Lists containing this project

README

          

# Type Class resolution for Java

[![codecov](https://codecov.io/gh/Garciat/java-type-classes/branch/main/graph/badge.svg)](https://codecov.io/gh/Garciat/java-type-classes)
[![Maven Central Version](https://img.shields.io/maven-central/v/com.garciat.typeclasses/java-type-classes)](https://central.sonatype.com/artifact/com.garciat.typeclasses/java-type-classes)

## Background

Type classes are a powerful abstraction mechanism popularized by Haskell.

This library implements type class resolution for Java, allowing you to define
type classes and their instances (witnesses) in a modular fashion, and summon
them automatically at runtime.

For a tutorial-like explanation, see: https://garciat.com/posts/java-type-classes/

## Installation

The library is published on Maven Central as [com.garciat.typeclasses/java-type-classes](https://central.sonatype.com/artifact/com.garciat.typeclasses/java-type-classes)

For the core resolution model:

```xml

com.garciat.typeclasses
java-type-classes-core
0.1.5

```

For some predefined type classes & instances:

```xml

com.garciat.typeclasses
java-type-classes-instances
0.1.5

```

For the annotation processor:

```xml



maven-compiler-plugin



com.garciat.typeclasses
java-type-classes-core
0.1.5




```

## API

```java
@interface TypeClass {
@interface Witness {}
}

interface Ty {} // witness type token

class TypeClasses {
static T witness(Ty ty);
}
```

Where:

- For a witness type `C`, `witness()` looks for witness
constructors in `C` and `T1, T2, ..., Tn`.
- Witness constructors for a type `T` are its `public static` methods annotated
with `@TypeClass.Witness`.
- For a witness constructor `C ctor(D1, D2, ..., Dn)`, the witness
dependencies `D1, D2, ..., Dn` are resolved recursively.
- Resolution fails when multiple witness constructors exist for a witness type,
after applying overlapping instances reduction.
- Resolution fails when a witness constructor for a witness type cannot be
found.
- Witness summoning is the result of recursively invoking witness constructors
up their respective dependency trees.
- `T witness(Ty)` summons a witness of type `T` or fails with a runtime
exception of type `TypeClasses.WitnessResolutionException`.

## Example

```java
// Type class definition
@TypeClass
public interface Show {
String show(T value);

// Helper for inference:
static String show(Show showT, T value) {
return showT.show(value);
}

// Witness definitions:

// "Leaf" witness with no dependencies:
@TypeClass.Witness
static Show integerShow() {
return i -> Integer.toString(i);
}

// Witness with dependencies (constraints):
@TypeClass.Witness
static Show> listShow(Show showA) {
return listA -> listA.stream().map(showA::show).collect(Collectors.joining(", ", "[", "]"));
}
}

// Custom type
record Pair
(A first, B second) {
@TypeClass.Witness
public static
Show> pairShow(Show showA, Show showB) {
return pair -> "(" + showA.show(pair.first()) + ", " + showB.show(pair.second()) + ")";
}
}

// Usage
class Example {
void main() {
Pair> value = new Pair<>(1, List.of(2, 3, 4));

// Summon (and use) the Show witness for Pair>:
String s = Show.show(witness(new Ty<>() {}), value);

System.out.println(s); // prints: (1, [2, 3, 4])
}
}
```

## Other features

- Support for higher-kinded type classes like `Functor>`, `Monad>`, etc.
- See the `api.hkt` package for details.
- Support for overlapping instances _a la_ Haskell.
- Based
on [this GHC spec](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/exts/instances.html#overlapping-instances).

## Future work

- Annotation processor:
- To reify the witness graph at compile time.
- To support parameterless `witness()` calls.
- Caching of summoned witnesses.