Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Higher Kinded Type machinery for Java

License

NotificationsYou must be signed in to change notification settings

derive4j/hkt

Repository files navigation

GitterMaven CentralTravis

This project provides type-safety for the higher kinded type encoding demonstrated inhttps://github.com/highj/highj via a JSR269 annotation processor.

For some theorical explanation of the encoding you may refer to theLightweight higher-kinded polymorphism paper.

Usage

Choose your HK encoding:

the two basic possibilities are:

classHkTest<A>implements__<HkTest<?>,A> {...}

and

classHkTest<A>implements__<HkTest.w,A> {enumw {// could be any name, also could be a static nested class.  }}

We say that__<HkTest.w, A> is the HK encoding of HkTest and callw thewitness type ofHkTest.

What about binary type constructors ? Ternary ? And more ?

@derive4j/hkt supplies interfaces__<f, A>,__2<f, A, B> up to__9<f, A, B, C, D, E, F, G, H, I>.

For example, a disjoint union type commonly called "Either" could be declared this way :

classEither<A,B>implements__2<Either.µ,A,B> {enumµ {}  ...}

Obligatory Monad example:

The higher kinded polymorphism gained by the encoding allows us to express things that are normally inexpressible in Java. Eg.:

publicinterfaceMonad<m> {  <A>__<m,A>pure(Aa);  <A,B>__<m,B>bind(__<m,A>ma,Function<A,__<m,B>>f);default <A,B>__<m,B>map(__<m,A>ma,Function<A,B>f) {returnbind(ma,f.andThen(this::pure));  }}

Aliases interfaces

You may want to create aliases of derive4j hkt__* interfaces that better suit your naming preferences, maybe also addingsome default methods. Eg.:

interfaceHigherKind1<TCextendsHigherKind1<TC, ?>,T>extends__<TC,T> {default <R>Rtransform(Function<__<TC,T>,R>f) {returnf.apply(this);  }}

And so your hk-encoded classes would look like:

classHkTest<A>implementsHigherKind1<HkTest<?>,A> {...}

In any case, just try: if you do something wrong the annotation processor shall help you!

A note on safety : do not cast! Use the generated safe cast methods

By default the annotation processor will generate aHkt class in each package that contains hk-encoded classes.

The generated class contains casting methods and factories ofTypeEq that allow you to safely recover the original type from its hk-encoding.

Here is an example :

  • given the HKT types
classMaybe<A>implements__<Maybe.µ,A> {...}

and

classList<A>implements__<List.µ,A> {...}

both in packagemyorg.data

  • then the following class will be generated
packagemyorg.data;finalclassHkt {privateHkt() {}static <A>Maybe<A>asMaybe(final__<Maybe.µ,A>hkt) {return (Maybe<A>)hkt;  }static <A>List<A>asList(final__<List.µ,A>hkt) {return (List<A>)hkt;  }}

Now you may ask : why is that safe ? I could implement__<Maybe.µ, A> in myFoo<A> class, pass an instance of it toHkt.asMaybe and then boom !

And to this the answer is no, you can't. That's the whole point of the hkt processor : would you try to implement__<Maybe.µ, A> in any other class thanMaybe, you'd get acompile time error.

The processor thus ensures that the only possible implementation of__<Maybe.µ, A> isMaybe<A> : hence the safety of the cast in the generated methods.

Configuration of code generation

Code generation can be customized by using theHktConfig annotation (onpackage-info or classes).

Consider the example of the previous section : we would like the generated methods to be calledtoX instead ofasX. Easy ! Just declare, in themyorg.data package, apackage-info file as such :

@HktConfig(coerceMethodName ="to{ClassName}")packagemyorg.data;

Note that configuration is handled hierarchically through packages, classes and inner classes. That means that would you want to keep yourtoX methods and at the same time have the one forList generated in its own class, you could declare apackage-info as afore mentionned and then annotate theList class this way:

@HktConfig(generateIn ="MyHktList")classList<A>implements__<List.µ,A> {...}

As expected, the following two files would then be generated :

packagemyorg.data;finalclassHkt {privateHkt() {}static <A>Maybe<A>toMaybe(final__<Maybe.µ,A>hkt) {return (Maybe<A>)hkt;  }}

and

packagemyorg.data;finalclassMyHktList {privateMyHktList() {}static <A>List<A>toList(final__<List.µ,A>hkt) {return (List<A>)hkt;  }}

I want it !

Maven

<dependency>  <groupId>org.derive4j.hkt</groupId>  <artifactId>hkt</artifactId>  <version>0.9.2</version></dependency>

Gradle

compile(group: 'org.derive4j.hkt', name: 'hkt', version: '0.9.2', ext: 'jar')

[8]ページ先頭

©2009-2025 Movatter.jp