Last active
May 2, 2022 08:05
-
-
Save pthariensflame/3916060 to your computer and use it in GitHub Desktop.
Higher-Ranked types in Java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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