Skip to content

Instantly share code, notes, and snippets.

@pthariensflame
Last active May 2, 2022 08:05
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pthariensflame/3916060 to your computer and use it in GitHub Desktop.
Save pthariensflame/3916060 to your computer and use it in GitHub Desktop.
Higher-Ranked types in Java
/**
* You can encode Haskell's `RankNTypes` extension in terms of
* the much less immediately powerful `PolymorphicComponents`
* extension. Java has a direct analogue to
* `PolymorphicComponents`: method-level generics!
*
* This class is useful for the demonstration, but does not
* itself make use of higher-ranked types. It simulates
* Haskell's `(->)` type constructor.
*/
public abstract class Func<A, B> {
public abstract B apply(A input);
}
/**
* This is equivalent to the following Haskell datatype:
* > newtype Codensity a = Codensity { runCodensity :: forall r. (a -> r) -> r }
* This is a simple use of `PolymorphicComponents`.
*/
public abstract class Codensity<A> {
public abstract <R> R run(Func<A, R> continuation);
}
/**
* This simulates the following rank-2 Haskell function type:
* > runST :: forall a. (forall s. ST s a) -> a
*/
public abstract class ST<S, A> {
protected abstract A impl();
public static A run(STForallS<A> stfs) {
return stfs.get<RealWorld>().impl();
}
public static abstract class STForallS<A> {
public abstract <S> ST<S, A> get();
}
public static final class RealWorld {
private RealWorld() {}
}
}
/**
* This simulates the following rank-3 Haskell function type:
* > fixResourceHandlerMapper :: forall r1 r2 r3 a. (forall b. (forall c. (r1 -> c) -> c) -> (r2 -> b) -> b) -> (r3 -> a) -> a
*/
public abstract class ResourceHandlerMapper<R1, R2, B> {
protected abstract ResourceHandler<R2, B> impl(ResourceHandler.PolyInX<R1>);
public <R3, A> ResourceHandler<R3, A> fix() {
// Somehow get a lazy fixpoint in Java... :/
}
/**
* Notice that I could also have simply used `Func<Func<R, X>, X>`
* instead of `ResourceHander<R, X>` and gotten exactly equivalent
* results, although I would then have to find a different place to
* put `PolyInX`.
*/
public static abstract class ResourceHandler<R, X> {
public abstract X withResource(Func<R, X>);
public static abstract class PolyInX<R> {
public abstract <X> ResourceHandler<R, X> get();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment