views:

341

answers:

8

Its often hear that Haskell(which I don't know) has a very interesting type system.. I'm very familiar with Java and a little with C#, and sometimes it happens that I'm fighting the type system so some design accommodates or works better in a certain way.

That led me to wonder...

What are the problems that occur somehow because of deficiencies of Java/C# type system? How do you deal with them?

+1  A: 

I don't like the fact that classes are not first-class objects, and you can't do fancy things such as having a static method be part of an interface.

pgb
Small point: with C# 3 you can add extension methods to interfaces, which amounts to the same thing.
Barry Fandango
@Barry that's incorrect, you still need to have an instance of the interface to be able to call an extension method. A static method on an interface would allow you to call the method regardless or whether or not you had an instance.
Joseph
Ah, I see the distinction, thanks.
Barry Fandango
+4  A: 

Arrays are broken.

  Object[] foo = new String[1];
  foo[0] = new Integer(4);

Gives you java.lang.ArrayStoreException

You deal with them with caution.

Nullability is another big issue. NullPointerExceptions jump at your face everywhere. You really can't do anything about them except switch language, or use conventions of avoiding them as much as possible (initialize fields properly, etc).

More generally, the Java's/C#'s type systems are not very expressive. The most important thing Haskell can give you is that with its types you can enforce that functions don't have side effects. Having a compile time proof that parts of programs are just expressions that are evaluated makes programs much more reliable, composable, and easier to reason about. (Ignore the fact, that implementations of Haskell give you ways to bypass that).

Compare that to Java, where calling a method can do almost anything!

Also Haskell has pattern matching, which gives you different way of creating programs; you have data on which functions operate, often recursively. In pattern matching you destruct data to see of what kind it is, and behave according to it. e.g. You have a list, which is either empty, or head and tail. If you want to calculate the length, you define a function that says: if list is empty, length = 0, otherwise length = 1 + length(tail).

If you really like to learn more, there's two excellent online sources:

Learn you a Haskell and Real World Haskell

egaga
I'm not sure I understand the example. foo contains a string array, so trying to set foo[0] to an integer should fail - isn't that the point of a type system?
Barry Fandango
No. The point of a type system is that it shouldn't compile.
mquander
ah, gotcha, thanks
Barry Fandango
A: 

(Re: C# specifically.)

I would love tagged unions.

Ditto on first-class objects for classes, methods, properties, etc.

Although I've never used them, Python has type classes that basically are the types that represent classes and how they behave.

Non-nullable reference types so null-checks are not needed. It was originally considered for C# but was discarded. (There is a stack overflow question on this.)

Covariance so I can cast a List<string> to a List<object>.

Colin Burnett
Non-nullable reference types would be nice! Spec#, a C#-extension, includes them.Covariance will exist in the next C#-version.
Dario
The .NET System.Type class represents types. What makes the Python type first-class, and the .NET Type not?
Barry Fandango
@Barry. System.Type is first class but it's not the class (that is *key*). I cannot create "public class Foo {}" and later do "Foo.MyFunMethod = funmethod" to add a new method (either before or after compiling). Perhaps prototyping in Javascript is more familiar to you?
Colin Burnett
Colin, I see what you're getting at. So mutability is a condition for first-class-ness.
Barry Fandango
Colin Burnett
Thanks for the info, it's appreciated!
Barry Fandango
A: 

Type erasure in Java.

Paul Morie
A: 

This is minor, but for the current versions of Java and C# declaring objects breaks the DRY principle:

Object foo = new Object; 
Int x = new Int;
Rob Allen
Albeit with C# you can just use "var x = new Whatever();" and the compiler will do the right thing for you
Camilo Díaz
It has gotten better and with C# 3 you can use local type inference (var x = 0; instead of Int x = 0;) but we aren't in Python/Ruby territory yet
Rob Allen
+3  A: 

I dislike the fact that there is a differentiation between primitive (native) types (int, boolean, double) and their corresponding class-wrappers (Integer, Boolean, Double) in Java.

This is often quite annoying especially when writing generic code. Native types can't be genericized, you must instantiate a wrapper instead. Generics should make your code more abstract and easier reusable, but in Java then bring restrictions with obviously no reasons.

private static <T> T First(T arg[]) {
 return arg[0];
}

public static void main(String[] args) {  
 int x[] = {1, 2, 3};
 Integer y[] = {3, 4, 5};

 First(x); // Wrong
 First(y); // Fine
}

In .NET there is no such problems even if there separate value and reference types, because they strictly realized "everything is an object".

Dario
A: 

None of them have meta-programming facilities like say that old darn C++ dog has.

Using "using" duplication and lack of typedef is one example that violates DRY and can even cause user-induced 'aliasing' errors and more. Java 'templates' isn't even worth mentioning..

rama-jka toti
+1  A: 

this question about generics shows the deficiencies of the java type system's expressiveness
http://stackoverflow.com/questions/876948/higher-kinded-generics-in-java

Chii