3

I'm studying Haskell and came across polymorphic values. These are the values that have different type depending on the context. For example, Nothing has type Maybe a or [] has type [a]. So [] is list of anything you want and you can use it everywhere any list is expected.

I struggle to find a similar thing in Java, apart from "billion-dollar mistake" null, which is basically of any type. May be generics with unbounded wildcard is similar, but again, I can't think of an example.

Is there something similar in Java?

Konstantin Milyutin
  • 11,946
  • 11
  • 59
  • 85
  • Given `null` is one of the most used and re-used techniques in many languages, a billion-dollar mistake is likely to be sensationalised, some people struggle with it esp beginners but I don't see it as a problem. An `Object` reference can point to any object type. – Peter Lawrey Jan 19 '16 at 20:21
  • 1
    I think generics is the thing that comes the closest but it's still a long way away. Overall though, I don't think it's a very productive idea to try to map ideas one-to-one from two such different paradigms. For example, a kind of polymorphism is built into inheritance, a variable of type `Object` can hold any value, but it doesn't work the other way around. Does that stunted parallel help you understand either Haskell or Java better? I doubt it. – biziclop Jan 19 '16 at 20:21
  • 3
    Polymorphic values values work through _parametric polymorphism_, which Java doesn't have. So, this is basically impossible in the same way inheritance is “impossible” in C: you can certainly emulate it in several ways ([obviously](https://en.wikipedia.org/wiki/Turing_completeness)), but whether that's sensible or you wouldn't be off better with something more idiomatic is doubtful. – leftaroundabout Jan 19 '16 at 20:22
  • 2
    Generics are a form of parametric polymorphism. This is more a matter of syntax and type inference. – Tobias Brandt Jan 19 '16 at 20:43
  • You might want to look at https://github.com/eallik/learning-haskell-runtime-in-java – Erik Kaplun Jan 19 '16 at 22:11

2 Answers2

7

This is more a comment than an actual answer, but I require more space.

While the type systems of Java and Haskell are quite apart, some similarities can be found in certain features. Here are a few examples: just keep in mind that there is no perfect correspondence between the related constructs shown below.

Polymorphic functions (as in FP, not OOP polymorphism):

fst :: forall a b. (a, b) -> a
fst (x,y) = x
<A,B> A fst(A a, B b) {
    return a;
}

Note that polymorphic non-function values can not be translated as easily. Even in Haskell, values such as 3 :: Num a => a are functions in disguise. Further, [] :: [a] and Nothing :: Maybe a are also treated as functions, taking a "type" parameter in some stages of compilation -- albeit, IIRC at runtime these parameter disappear.

Type arguments:

data T a = T a Int a
class T<A> {
    A x;
    int n;
    A y;

    T(A x, int n, A y) {
        this.x = x; this.n = n; this.y = y;
    }
}

Algebraic data types (e.g. data with many constructors): these are not directly available in Java. Some other JVM languages, like Scala, have ADT supported directly in the language, as well as pattern patching and non-exhaustiveness warnings. In Java, you can use the so-called Visitor pattern to simulate ADT value elimination, which is a basic form of pattern matching.

chi
  • 111,837
  • 3
  • 133
  • 218
  • The problem with your first example is that `fst` is not a value in Java. A method reference like `YourClass::fst` is, but it isn't polymorphic: it'll only work if it infers `A` and `B`. – Alexey Romanov Jan 20 '16 at 06:44
2

A polymorphic value like [] can only be represented as a method in Java. In fact, this method already exists in the Arrays class and is called asList. And because of Java's type inference, you don't even need to provide type arguments:

import java.util.Arrays;
import java.util.List;

public class Test {
    public static void main(String[] args) {
        List<String> myList = Arrays.asList();
    }
}

If you ignore all the noise, []Arrays.asList().

Tobias Brandt
  • 3,393
  • 18
  • 28
  • 4
    Good answer. But I guess it's better to use `Collections.emptyList()` since `Arrays.asList()` allocates a new object each time you invoke it. However, `Collections.emptyList()` is immutable. – Mateusz Herych Jan 19 '16 at 20:44