Skip to content

Instantly share code, notes, and snippets.

@danieldietrich
Last active August 29, 2015 14:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danieldietrich/6320d0d617ededbe05f7 to your computer and use it in GitHub Desktop.
Save danieldietrich/6320d0d617ededbe05f7 to your computer and use it in GitHub Desktop.
Java Shared Types
/*
* Java Quest
* ==========
*
* Write a method in two different contexts (read: Types)
* which takes a function which returns an object of the current type.
*
* T1<A> { <B> T1<B> m(f: A -> T1<B>); }
* T2<A> { <B> T2<B> m(f: A -> T2<B>); }
*
* Then write a T of type T1 and T2 which also declares the method.
*
* T<A> extends T1<A>, T2<A> { <B> T<B> m(f: A -> T<B>); }
*/
// Used for type declaration only
interface Manifest<A, M extends Manifest<?, M>> {
}
// These two guys declare the same method. The `mapper` is important here.
interface Foldable<A, CLASS extends Foldable<?, CLASS>> extends Manifest<A, CLASS> {
<B, FOLDABLE extends Manifest<B, CLASS>> Foldable<B, CLASS> flatMap(Function<? super A, FOLDABLE> mapper);
}
interface Monad<A, CLASS extends Monad<?, CLASS>> extends Manifest<A, CLASS> {
<B, MONAD extends Manifest<B, CLASS>> Monad<B, CLASS> flatMap(Function<? super A, MONAD> mapper);
}
// Hah! The actual type is shared via Manifest.
interface List<A> extends Foldable<A, List<?>>, Monad<A, List<?>> {
@Override
<B, LIST extends Manifest<B, List<?>>> List<B> flatMap(Function<? super A, LIST> mapper);
}
// Note: In this solution, an implementation of flatMap has to perform an unchecked cast.
@danieldietrich
Copy link
Author

The short version, describing the solution of the quest:

interface T1<A, C extends T1<?, C>> extends Manifest<A, C> {
    <B, M extends Manifest<B, C>> T1<B, C> m(Function<? super A, M> f);
}
interface T2<A, C extends T2<?, C>> extends Manifest<A, C> {
    <B, M extends Manifest<B, C>> T2<B, C> m(Function<? super A, M> f);
}
interface T<A> extends T1<A, T<?>>, T2<A, T<?>> {
    @Override
    <B, M extends Manifest<B, T<?>>> T<B> m(Function<? super A, M> f);
}

where

interface Manifest<A, M extends Manifest<?, M>> {
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment