News for hackers. Stuff that matters.
Re:The Unsound Playground: Java and Scala's Type Systems are... by derriz on Sunday November 27, 2016 @03:44PM (#13051415)
It was unsound from the first version with respect to arrays. If B is a subtype of A, then Java allows you to pass as an argument (or return) an array of B where an array of A is specified in the type signature.

To see why this is broken, consider a method that takes an array of Animal and sets the first element to be a Cat instance. Java's type system will allow you to call this method with an array of Dog which will blow up at runtime on the assignment to the array element.

I noticed this immediately when I first started using Java (version 1.0.4!) as I had just read the classic 1985 OO type systems paper by Cardelli. I didn't have an OO background and was surprised that a "modern" language like Java would have this flaw in its type system given that the problem was well known years before.

Re:The Unsound Playground: Java and Scala's Type Systems are... by dvt on Monday November 28, 2016 @01:41AM (#13053833)
This, imo, is actually a bigger deal than generics. Since type erasure does all kinds of "magic", it doesn't surprise me that there will end up some kind of (T)-type casts somewhere in the OP's bytecode.

But the fact that the following is unsound (and has been for a while) will always remain a mystery to me:

  public class Main {
  
  	class Animal {}
  	class Dog extends Animal {}
  	class Cat extends Animal {}
  
  	public static void main (String[] args)  {
  		Main x = new Main();
  		Dog[] doges = new Dog[10];
  		x.t(doges);
  	}
   
  	public void t(Animal[] bar) {
  		bar[0] = new Cat();
  		bar[0] = new Animal(); // also breaks
  	}
  
  }
The array type seems completely tractable and may be able to be caught by the compiler.
Re:The Unsound Playground: Java and Scala's Type Systems are... by krona on Monday November 28, 2016 @09:05AM (#13055443)
> The array type seems completely tractable and may be able to be caught by the compiler.

This isn't an error, it was a design decision: https://en.wikipedia.org/wiki/Covariance_and_contravariance_...

You could call it bad design, but fixing it would (imo) just make Java even worse than it already is.

Re:The Unsound Playground: Java and Scala's Type Systems are... by dvt on Monday November 28, 2016 @03:07PM (#13057961)
My point had nothing to do with the merits of covariant types, just tractability. It seems that the array's type is tractable so the compiler should (at least) give a warning.
Re:The Unsound Playground: Java and Scala's Type Systems are... by JoshTriplett on Monday November 28, 2016 @03:13AM (#13054111)
This would be fine if t's array bar only allowed mutation of the objects within the array, but didn't allow mutation of the array itself. Treating a Dog as an Animal works fine; however, you can only treat a Dog[] as a const Animal[], not a mutable Animal[].
Re:The Unsound Playground: Java and Scala's Type Systems are... by trendkill on Monday November 28, 2016 @01:54AM (#13053867)
A joke from my childhood:

  Man goes to doctor, 
  and says:
  
  "Gee, doc, it 
   really hurts 
   when I do this."

  Doctor replies:

  "Then don't do that."
Re:The Unsound Playground: Java and Scala's Type Systems are... by paulddraper on Monday November 28, 2016 @02:32AM (#13053983)
Two men stand on a bridge. The first leans on the railing, which gives way and sends him over the edge.

Horrified, the second looks around and spots a civil engineer. Engineer shrugs and says, "Don't do that."

Re:The Unsound Playground: Java and Scala's Type Systems are... by TeMPOraL on Monday November 28, 2016 @03:26AM (#13054143)
Ha ha. Funny joke. Now let's get back to discussing the future applications of JavaScript in air travel...

;).

Re:The Unsound Playground: Java and Scala's Type Systems are... by zphds on Tuesday November 29, 2016 @04:00PM (#13066247)
"Don't do that"
Re:The Unsound Playground: Java and Scala's Type Systems are... by mvindahl on Monday November 28, 2016 @04:08AM (#13054277)
On the positive side, these kind of errors tend to blow up immediately when the code is executed. Assuming that you have a semi-decent test suite, it won't make it to production. The language type system won't save your butt but your unit tests will.

There is a deeper discussion here; if you are writing good automatic tests anyway, which I hope you are, then of how much value is a rigorious type system? :)

Re:The Unsound Playground: Java and Scala's Type Systems are... by greydius on Monday November 28, 2016 @10:48AM (#13056136)
I agree that a comprehensive test suite is valuable, but I don't think it's safe to assume that errors like this will always be caught, no matter how good your tests are. It's not reasonable to write a test for every possible situation that could ever occur. In fact, it's a giant waste of time.

> of how much value is a rigorous type system?

It saves a lot of time on those tests you won't have to write and maintain just to ensure that you're getting your types correct. Strong static types are also good documentation. Some type systems (e.g. Haskell) can even explicitly indicate whether a procedure is pure or has effects. Static types also enable dispatch that can be resolved at compile-time, resulting in more efficient execution. And the list goes on.

Of course, advocates of languages without static types have heard and dismissed all these arguments before. I guess it's really just a matter of taste.

Re:The Unsound Playground: Java and Scala's Type Systems are... by mvindahl on Tuesday November 29, 2016 @04:36AM (#13061939)
I've heard both sides of the static types vs dynamic types argument a lot of times. I don't think there will ever be any kind of universal agreement but I find the discussion to be interesting.

For the record, I personally think a language like Typescript hit a sweet spot. Not a lot of mandatory ceremony but you have the choice to add types where it matters, e.g. at interface level. Also the duck typing saves you from inventing class names for all kind of almost-primitive types.

Re:The Unsound Playground: Java and Scala's Type Systems are... by dllthomas on Monday November 28, 2016 @10:52PM (#13060640)
> if you are writing good automatic tests anyway, which I hope you are

"Don't write tests. Generate them."

Re:The Unsound Playground: Java and Scala's Type Systems are... by Jean-Philipe on Monday November 28, 2016 @12:22AM (#13053581)
Another fundamental flaw in my opinion is the cats-and-dogs analogy frequently used to highlight the use of inheritance in OO.

Cats and dogs being mammals is a taxonomy. It's data, not code. Unfortunately, I see OO programmers coding taxonomies all the time just for the sake of it, ending up with deep inheritance trees of classes without ever taking the step back and asking themselves, why they do it the first place. (e.g. to share functionality or to reuse code)

Re:The Unsound Playground: Java and Scala's Type Systems are... by willtim on Monday November 28, 2016 @01:00AM (#13053696)
Taxonomies are common in the real world, so it is natural to try to model them. If the language lacks sum types (the mathematical dual of product types, a.k.a. tagged unions) then programmers are forced into using inheritance to encode it. So I blame the language, not the programmers.
Re:The Unsound Playground: Java and Scala's Type Systems are... by gregoor on Monday November 28, 2016 @03:05AM (#13054079)
I understood JP's critique to be more about mixing behaviour with data than about alternative ways of modelling inheritance.
Re:The Unsound Playground: Java and Scala's Type Systems are... by willtim on Monday November 28, 2016 @12:47PM (#13057031)
But Java strongly encourages the mixing of data and behaviour. There is only virtual method dispatch and switch on ints/enums for efficient case analysis. We therefore need complex encodings like the Visitor pattern, if we are to avoid conflating data and behaviour. So again, I blame the language not the programmers.
Re:The Unsound Playground: Java and Scala's Type Systems are... by MrBuddyCasino on Sunday November 27, 2016 @04:12PM (#13051560)
Is this a defect or a tradeoff? Passing arrays of subtypes seems useful to me. I never experienced such an error, but I suspect this is quickly caught and shouldn't be a big problem.

But then I don't know anything about type system theory.

Re:The Unsound Playground: Java and Scala's Type Systems are... by Groxx on Sunday November 27, 2016 @05:34PM (#13052019)
Without generics (this is java 1, remember) it seems like a reasonable tradeoff. Otherwise[1] you can't have array-modifying polymorphic code at all - how would you write a "reverse this array" function, for instance? You'd need one for every kind of array you want to reverse. Or a "copy" function - even if you're given a properly-sized-and-typed array to put the values in, you can't make a function that'd work on anything except a single type.

You could force every array-function-caller to cast their args to e.g. `Object[]`, but that seems like it'd require more work for even less safety. Though I'd love a read-only concept in Java, for read purposes :|

[1]: I think. If I'm wrong, someone please correct me!

Re:The Unsound Playground: Java and Scala's Type Systems are... by RHSeeger on Sunday November 27, 2016 @08:40PM (#13052841)
You could define what an array accepts vs returns separately (input vs output). Admittedly, you're pretty much into generics (good ones, not what Java has) at that point.

Edit: Could use a better word for "good" that sounds less dismissive, but I couldn't think of one. Java's generics are lacking in certain areas, unfortunately.

Re:The Unsound Playground: Java and Scala's Type Systems are... by MrBuddyCasino on Monday November 28, 2016 @04:09AM (#13054283)
Generics in Java are pretty complicated already, so much so that very few developers fully understand them. I'm not sure the gain in complexity would be worth the added safety.

I'd like to see examples in languages where this is possible, if there are any?

Re:The Unsound Playground: Java and Scala's Type Systems are... by int_19h on Sunday November 27, 2016 @04:28PM (#13051638)
It is both.

Passing collections of subtypes where a read-only collection of supertypes is expected by the receiving code is fine, because the receiving code can't do anything that would break type safety.

But Java decided to only have a single array type, as a matter of expediency. But they also wanted covariance, because, as you point out, sometimes it's just convenient - more expediency. And so the trade-off was to enforce safety at runtime.

It's still a defect in a sense that the design itself could be made sound, if there were a read-only array reference type in Java.

Re:The Unsound Playground: Java and Scala's Type Systems are... by marvy on Sunday November 27, 2016 @11:27PM (#13053400)
Read-only is too strict. Can't reverse the array, or sort it.
Re:The Unsound Playground: Java and Scala's Type Systems are... by int_19h on Monday November 28, 2016 @03:31AM (#13054157)
Sure you can - you just need to copy it.

And I didn't mean to imply that array references should always be read-only. What I meant is that there should be a way to say "the referenced array cannot be mutated through this reference", like const* in C. 90% of the time, when you pass or return arrays, this is exactly what you want.

Re:The Unsound Playground: Java and Scala's Type Systems are... by nradov on Sunday November 27, 2016 @08:48PM (#13052868)
The existence of arrays at all is a trade off. The language would be more type safe and more consistent with OO best practices without arrays and using dynamic random access lists instead. But that would be too slow for some applications.
Re:The Unsound Playground: Java and Scala's Type Systems are... by emmelaich on Sunday November 27, 2016 @05:42PM (#13052061)
I think it is a fundamental.

Just because D isa B it does not mean list(D) isa list(B).

Re:The Unsound Playground: Java and Scala's Type Systems are... by prodigal_erik on Sunday November 27, 2016 @07:45PM (#13052631)
What we need is

  listContaining(Dog) isa listContaining(Animal)
  listAccepting(Animal) isa listAccepting(Dog)
Re:The Unsound Playground: Java and Scala's Type Systems are... by STRML on Sunday November 27, 2016 @09:11PM (#13052944)
Which is precisely the idea of covariant getters / contravariant setters in some sounder languages.
Re:The Unsound Playground: Java and Scala's Type Systems are... by Kreeg on Monday November 28, 2016 @06:36AM (#13054789)
IIRC, Scala has covariant/contravariant generics

(apologies for the bad terminology, I'm not too familiar with the details)

Re:The Unsound Playground: Java and Scala's Type Systems are... by Groxx on Wednesday November 30, 2016 @12:28AM (#13068695)
support for "<? extends X>" and "<? super X>" is supporting covariant / contravariant. invariant would be "<x>".

basically. the same concept applies in a number of areas, with varying support (e.g. Java doesn't support contravariance in its method overloading: http://stackoverflow.com/a/2501513/16295 )

Re:The Unsound Playground: Java and Scala's Type Systems are... by quotemstr on Sunday November 27, 2016 @06:25PM (#13052256)
> Is this a defect or a tradeoff?

I'm curious what line of thinking could prompt this question. Not all trade-offs are good choices just because they're trade-offs! Maybe it has something to do with the recent spate of language design choices justified with "it was a trade-off", as if the words "trade-off" is an incantation that puts a technical decision above criticism.

Re:The Unsound Playground: Java and Scala's Type Systems are... by marvy on Sunday November 27, 2016 @11:32PM (#13053415)
> Not all trade-offs are good choices just because they're trade-offs.

Indeed. But they're not automatically bad choices either. Are you saying this one is a bad trade-off?

Re:The Unsound Playground: Java and Scala's Type Systems are... by plaguuuuuu on Sunday November 27, 2016 @05:58PM (#13052122)
Both defect and trade-off. I can definitely see value in being able to pass an array of Dogs and treat it as an array of Animals, but it means that the array of Animals is not really an array of animals (because certain properties of a real array of Animals actually cause the code to break) and as a result the language is a little dirtier for it. Like, that's pretty horrible to be honest.

What you really want in that instance is to be able to easily and explicitly cast the Dog[] to Animal[] before calling the method. A better language would make this easy instead. I think Java's Vector type can do it, so it surprises me that they allow that sort of type weirdness with arrays..

Re:The Unsound Playground: Java and Scala's Type Systems are... by marvy on Sunday November 27, 2016 @11:29PM (#13053405)
I think you're wrong about Vector
Re:The Unsound Playground: Java and Scala's Type Systems are... by vbezhenar on Monday November 28, 2016 @02:12AM (#13053921)
Yep, it's a huge hole. Arrays in Java should be Object[] or primitive[], not Animal[]. That's one of the reasons that object arrays should be avoided (something like ArrayList should be used instead).
Re:The Unsound Playground: Java and Scala's Type Systems are... by airplane on Sunday November 27, 2016 @06:02PM (#13052143)
Don't think the scenario perfectly fits because before generics you couldn't have a method that takes in an Array of Animal, just an Array.

Can a language could resolve this issue without generics or some other contract feature (which Java did later add), or without limiting the scope of array definitions and their use?

May be good to note that Array<Dog> doesn't actually extend Array<Animal>, so there shouldn't be any polymorphic usage between them, and the return statement and method call scenarios are compile time errors with proper generics.

Re:The Unsound Playground: Java and Scala's Type Systems are... by quotemstr on Sunday November 27, 2016 @06:05PM (#13052163)
> before generics you couldn't have a method that takes in an Array of Animal, just an Array.

Arrays aren't generic types like ArrayList. Arrays are core language constructs parameterized by their element types. Array types are not erased in Java.

Re:The Unsound Playground: Java and Scala's Type Systems are... by kuschku on Sunday November 27, 2016 @06:26PM (#13052268)
Ehm, no?

You can’t pass Dog[] where Animal[] is expected, it’s one of the more interesting properties of the Array, because its the only case where that doesn’t work.

For the exact reason you mentioned.

Re:The Unsound Playground: Java and Scala's Type Systems are... by pvg on Sunday November 27, 2016 @08:45PM (#13052857)
Re:The Unsound Playground: Java and Scala's Type Systems are... by aioprisan on Monday November 28, 2016 @02:30AM (#13053977)
Looks like you missed the gist of the post, then. Code it up, you'll see it in action very clearly.
Re:The Unsound Playground: Java and Scala's Type Systems are... by AnimalMuppet on Monday November 28, 2016 @01:13PM (#13057244)
I believe you missed the GP's point. It's not that "you can't because the language stops you", it's that "you can't because it doesn't work".

That is, you're agreeing, not disagreeing.