Search code examples
javagenericshaskellpolymorphismhigher-kinded-types

Higher-kinded generics in Java


Suppose I have the following class:

public class FixExpr {
  Expr<FixExpr> in;
}

Now I want to introduce a generic argument, abstracting over the use of Expr:

public class Fix<F> {
  F<Fix<F>> in;
}

But Eclipse doesn't like this:

The type F is not generic; it cannot be parametrized with arguments <Fix<F>>

Is this possible at all or have I overlooked something that causes this specific instance to break?

Some background information: in Haskell this is a common way to write generic functions; I'm trying to port this to Java. The type argument F in the example above has kind * -> * instead of the usual kind *. In Haskell it looks like this:

newtype Fix f = In { out :: f (Fix f) }

Solution

  • I think what you're trying to do is simply not supported by Java generics. The simpler case of

    public class Foo<T> {
        public T<String> bar() { return null; }
    }
    

    also does not compile using javac.

    Since Java does not know at compile-time what T is, it can't guarantee that T<String> is at all meaningful. For example if you created a Foo<BufferedImage>, bar would have the signature

    public BufferedImage<String> bar()
    

    which is nonsensical. Since there is no mechanism to force you to only instantiate Foos with generic Ts, it refuses to compile.