
Java Generics Are Turing Complete - ingve
http://arxiv.org/abs/1605.05274
======
chvid
In practice in means if you write stuff like this:

    
    
       interface Z {}
       interface N<x> {}
       interface L<x> {}
       interface Qlr<x> {}
       interface Qrl<x> {}
       interface E<x> extends
         Qlr<N<?super Qr<?super E<?super E<?super x>>>>>,
         Qrl<N<?super Ql<?super E<?super E<?super x>>>>> {}
       interface Ql<x> extends
         L<N<?super Ql<?super L<?super N<?super x>>>>>,
         E<Qlr<?super N<?super x>>> {}
       interface Qr<x> extends
         L<N<?super Qr<?super L<?super N<?super x>>>>>,
         E<Qrl<?super N<?super x>>> {}
       class Main {
           L<?super N<?super
           L<?super N<?super
           L<?super N<?super
           E<?super E<?super Z>>>>>>>>
         doit(
           Qr<? super E<? super E<? super Z>>> v
       ){
       return v;
       } }
    

You can make your compiler:

1\. Bark out an odd error. (Loop for a while and then stop due to an internal
stack overflow.)

2\. Compile something that gives a runtime type error.

------
Faint
DING! This is what always happens. If you want to get useful manipulations
done to code you'll eventually creep up to a Turing complete system. Now you
have a type system where you could calculate any program transformation,
albeit in really really convoluted, slow and ugly way.

It would have been SO much better to give the language proper macros to begin
with. I mean, a library that's actually meant for doing AST manipulations, and
a way to tell the compiler "apply this transformation to that code before
doing anything else with it", instead of another compiler-only interpreted
language inside the original language. People would not have to learn 2
different syntaxes, and compilation would probably be faster (well I'm
thinking more of heavily templating dependant C++ libraries here).

~~~
curried_haskell
Yo dawg, do you need a programming language inside your programming language?

~~~
exDM69
Yes. Otherwise you'll end up with an ugly Python or Perl script that generates
code, coupled with ugly build system hacks to make it work. This will happen
sooner or later.

~~~
DonHopkins
The Java culture fetishizes code generation. It's like somebody decreed "We
want to take over the world, and one measure of that is lines of code. So
there should be a hell of a lot more Java code: start writing Java code that
generates more Java code!"

~~~
acjohnson55
Go culture, too, for that matter.

------
cromwellian
An GWT engineer and former Scala guy, Lex Spoon, proved a similar theorem
several years ago when we were upgrading generics for GWT-RPC. The GWT RPC
code generator has to reason about return types of methods and which classes
could possibly be deserialized say if you return a List of Foo.

Lex showed how to construct the peano arithmetic in Java generics and how to
formulate problems such that solving the question of what types could be
returned from An Rpc call with List would amount to deciding these small
theorems or problems and therefore the GWT SerializationTypeOracleBuilder
class would have to solve the halting theorem.

That's probably a wrong paraphrasing and maybe lex will see this and chime in
but I think the original discussion was lost forever ironically when Wave,
which was built with GWT, was shut down.

------
cleeus
btw, here is the URL for a Java-Generics-Program from the paper:
[https://gist.github.com/rgrig/b4cdaed3ed9a70dbdb6f158f14b572...](https://gist.github.com/rgrig/b4cdaed3ed9a70dbdb6f158f14b57263)

comment from the source:

    
    
      // Encodes a Turing machine that counts in binary, and then halts.
      // Gives stack overflow by default.
      // If you increase the stack size (javac -J-Xss100M Main.java),
      // then it type-checks, but it takes a lot of time.

------
amelius
Now the waiting is for the first compiler that compiles to Java Generics.

------
brudgers
So is XSLT:
[http://www.unidex.com/turing/utm.htm](http://www.unidex.com/turing/utm.htm)

------
vesinisa
What does this mean in practice? That I can compute an arbitrary algorithm
with Java generics? How?

~~~
rntz
What it means in practice is that any Java typechecker is either (a)
incomplete - it will disallow some programs that should typecheck; (b) unsound
- it will allow some programs that shouldn't typecheck; or (c) non-total - it
will fail to terminate on some programs. (Or some combination of these three.)

~~~
gpderetta
No, that's in theory. In practice not much: any practical sufficiently complex
type system quickly gets extended to become Turing complete; from time to time
the compiler might get yell at you when you hit the maximum allowed type
recursion limit, but usually everything just work.

I believe that type checking in unextended Hindley-Milner type systems is
exponential, so, even if the algo is guaranteed to terminate in theory it
might not do so before the heat death of the universe. Again, in practice
outside of test cases demonstrating this 'feature' it doesn't matter.

~~~
jameshart
"the compiler might get yell at you when you hit the maximum allowed type
recursion limit" is an example of the compiler failing to compile something
which is valid in the type system.

~~~
gpderetta
Sure, the point is that it happens rarely with real world code and you can
always bump the compiler limit.

~~~
jameshart
Right, but that's precisely how Turing completeness works. It's possible to
write a program that can figure out whether most real world code terminates.
All Turing completeness tells you is that no matter how clever that program
gets, there will be some programs (not necessarily 'real world programs')
which it won't be able to process. The fact that the Java programming language
is Turing complete doesn't prevent us being able to write programs in it
(indeed it means we _can_ write interesting programs in it!). It is just a
result that tells us there are some things we can't say about ALL Java
programs.

This is a similar result. The fact that the Java type system is turing
complete doesn't stop us expressing things with it. It just tells us there are
some things we can't say about ALL Java type declarations.

------
btilly
Is there a link to the paper?

Preferably one that you don't have to be at a university to read?

~~~
cwmma
[http://arxiv.org/pdf/1605.05274v1.pdf](http://arxiv.org/pdf/1605.05274v1.pdf)
in the upper right corner of the page

------
ngrilly
The title sounds like a bad news to my ears.

~~~
Avshalom
Eh, turing complete is a really low bar to clear. In practice it just means
the compiler can't be proved to halt on valid code.

Avoiding turing completeness requires either very very careful design OR
(trivially) a hard limit on size/iterations the compiler is allowed to make (a
sufficiently small limit, obviously we call many things turing complete
colloquially that have very low limits anyway like 8-bit cpus with ~kb of
memory)

~~~
TeeWEE
Turing complete is by now means a 'low bar'.. Turing complete means that a
language, system can compute anything. Anything that can be computed, can be
computed with java generics. Thats what it says. Its quite a important term.

~~~
Avshalom
Basically all you need for turing completeness is the ability to
jump/branch/ignore-some-bits on some criteria see SUBLEQ or cyclical tag
systems or XY combinators.

it's actually very hard to avoid in a system that is supposed to do some sort
of computation.

------
kodfodrasz
Too bad they are still pretty much useless in many cases because of type
erasure, and many type constraints cannot be expressed (eg. constructor
constraints)...

Still way better than no generics at all, but if you are used to better
implementations these random limitations can be really painful..

~~~
alimbada
Don't know why this is being downvoted. I've been on a Java project for the
last ~6 months after ~8 years of doing C#/.NET development. My brain hurts
from seeing all the stupid workarounds in Java because it doesn't have real
generics.

~~~
the_af
I guess it's one thing to claim Java generics have problems and another to
claim they are "useless".

They are a big improvement over not having generics and, in my experience, one
seldom sees those workarounds you mentioned. Sure, when they are necessary
they are ugly... but how often _are_ they needed in standard application code?

~~~
kodfodrasz
Last week wanted to use GSON in a generic method to deserialize to a type
which is generic type parameter, in a method of the abstract base class.
Unfortunately it could not be done without the implementations passing up
their .class via super constructor.

IMHO deserializing JSON is quite a common application code.

If you are really interrested I'd create example code, but (as being lazy, and
the mentioned code not being my property) I'd hope to take my word for granted
:)

edit: I wrote useless in many cases!

~~~
slantedview
There are ways to resolve generics declared on base classes:

[https://github.com/jhalterman/typetools](https://github.com/jhalterman/typetools)

...but proper support of reified generics certainly would have been better.

------
rubenolivares
whine whine whine. go make a language of your own then, that way it's going to
be perfect and have no flaws. oh wait, you wouldn't even know where to start.

~~~
hepta
You don't need to be a good chef to know a meal is awful. A lot of people use
the language (me included) and make it work, doesn't mean it's without fault.

