Java language specification on wildcards - java

I am going through this link (Chapter 4. Types, Values, and Variables) and did not understand below point:
The relationship of wildcards to established type theory is an interesting one, which we briefly allude to here. Wildcards are a restricted form of existential types. Given a generic type declaration G<T extends B>, G<?> is roughly analogous to Some X <: B. G<X>.
I appreciate if you provide good example to understand above point clearly.
Thanks in advance.

The wording and formatting of this statement are a bit unlucky*. The link in the answer by Maouven actually covers the general topic pretty well, but one can try to focus on the particular case of Java and Wildcards here:
Wildcards are a restricted form of existential types. Given a generic type declaration G, G is roughly analogous to Some X <: B. G.
This basically says that the type parameter of the G is any subtype of B. And this is always the case, even when you don't say it explicitly.
Consider the following snippet, which hopefully illustrates the point:
class B { }
class G<T extends B>
{
T get() { return null; }
}
public class Example
{
public static void main(String[] args)
{
G<?> g = null;
// This works, even though "G<?>" seemingly does not say
// anything about the type parameter:
B b = g.get();
}
}
The object that you obtain by calling g.get() is of type B, because the declaration of G<T extends B> guarantees that any type parameter (even if it is the ? wildcard) always be "at least" of type B.
(In contrast to that: If the declaration only was G<T>, then the type obtained from g.get() would only be of type Object)
The relationship is described as "roughly analogous" to the type theoretic notation. You can probably imagine this as saying: If the declaration is G<T extends B>, and you use the type G<?>, then this roughly (!) means: There exists a type X extends B, and the ? here stands for this (unknown) type X.
An aside: Note that this also refers to Insersection Types. If you declared the class as class G<T extends B & Runnable>, then the statements
B b = g.get();
Runnable x = g.get();
would both be valid.
* The "unlucky" formatting referred to the fact that the source code of this paragraph actually reads
... is roughly analogous to <span class="type">Some <span class="type">X</span> ...
making clearer that the word "Some" already is part of the type that is being defined there formally...

Wildcards are a restricted form of existential types, in the way they incorporate the principle of existential types in Java. You can refer to the link here which provide explanatory examples:
What is an existential type?

Related

Why is this assignment involving wildcards legal in Java?

Most questions about wildcards want to know why something sensible is rejected by the compiler. My question is the opposite. Why is the following program accepted by the compiler?
void test(List<? extends Number> g1, List<? extends Number> g2)
{
g1 = g2;
}
I tried to explain this from the Java Language Specification, but I have not found the answer. I had the impression from various descriptions of Java generics and wildcards that each use of a wildcard is captured as a completely new type, but apparently not here. I have not found any nasty behavior that follows from this assignment being allowed, but it still seems "wrong".
When I face these questions, I approach this in a slightly different manner.
First of all, every single wildcard is captured, everywhere, by javac. In plain english: every time javac "sees" a wildcard it is going to transform that (this is almost accurate as you will see further). Specifically, let's say we have this:
List<? extends Number> list;
javac will transform to:
List<X1> list
where X1 <: Number, where <: means it is a subtype of, as such : X1 is an unknown type that extends Number. This will happen for every single occurrence. And it might be very weird, at first, in some scenarios:
public static void main(String[] args) {
List<?> l = new ArrayList<String>();
one(l);
two(l, l); // fails
}
public static <T> void one(List<T> single){
}
public static <T> void two(List<T> left, List<T> right){
}
capture conversion was applied individually to each List, it's like this happened:
two(List<X1>, List<X2>)
Now to why is your example accepted, is far more interesting, imho. You know that capture conversion is applied, but according to the JLS it is not applied everywhere:
If the expression name is a variable that appears "on the left hand side", its type is not subject to capture conversion.
It's like saying that only values are capture converted, not variables.
So in this case:
g1 = g2;
g1 has not been capture converted, while g2 has. It's like doing:
List<? extends Number> g1 = List<X1> (g2) // pseudo-code
We know that X1 <: Number so, as such List<X1> is a subtype of List<? extends Number>, so the assignment works.
Even if you change ? extends Number to ? (this is not a bounded wildcard anymore), this would still work.
List<? extends Number> is best read as:
This is a list of numbers, but, covariantly.
In other words, this is a list of some concrete but unknown type. However, I do know that, whatever type it might be, at least it is either Number or some subclass thereof.
Generics is weird; once you opt into some variance, you get the restrictions to go along with that. In the case of collections, 'covariance' comes with the baggage of 'no adding'.
Try it.
g1.add(XXX);
the only thing that is legal for XXX here? null. That's literally it. The full and complete and exhaustive list of all you can add to this thing. certainly Number x = 5; g1.add(x); is not going to be allowed by javac here.
By writing List<? extends a thingie> you're saying: Yeah, I want that. I'm signing up to this restriction that I get to add absolutely nothing (other than the academic case of literal null). In trade for handcuffing yourself, the things you can pass in for g1 is expanded considerably.
You can also opt into contravariance:
void foo(List<? super Integer> list) {
list.add(Integer.valueOf(5)); // works!
Integer x = list.get(0); // no go
}
contravariance is the opposite. add works. get doesn't work. Which in this case means: The type of the expression list.get(0) is just.. Object.
Now that we've covered that:
void test(List<? extends Number> g1, List<? extends Number> g2) {}
means 'my first parameter is a list of numbers, but I opt into covariance handcuffs', and 'my second parameter is a list of numbers, but I also opt into covariance handcuffs for this one too', it now makes sense why java lets you write g1 = g2. g2 is guaranteed to be an X<Y>, where X some concrete subclass of List, and Y is either Number or some subclass thereof.
This is 100% compatible, type-wise, with the notion of 'some sort of list whose type param is some covariant take on Number'. The only thing you can do a List<? extends Number> is to invoke methods of List where any T in the signatures are 'disabled' for parameters, and replaced by the bound (Number) for return types.
That's.. exactly what List<? extends Number> is describing, so it's compatible.
"I had the impression from various descriptions of Java generics and wildcards that each use of a wildcard is captured as a completely new type, "
That statement is correct.
So what? You are confusing the type of the object with the type of the variable.
Consider this code:
String s = "abc";
Object o = s;
o has type Object which is assignment compatible with the type of s. But that doesn't mean String and Object are the same type. No different with your example. You have two different List types for the objects, but one type for the variables. Each variable has type List<? extends Number>, so the assignment is fine. When you make the assignment, the object's generic type is List<x> for some completely new unknown type x. But the variable type remains List<? extends Number>.
How could it not be valid?
Both variables have identical type (in this case List<? extends Number>), so the compiler must allow assignment of one to the other.
The objects assigned to the variables may have different types, but the variable types are identical, so assignment is always legal.
The compiler does not know or care what the actual type of an object assigned to a variable is, even if it can be determined from the code. It cares only about declared types when checking types.

Why can the Monad interface not be declared in Java?

Before you start reading: This question is not about understanding monads, but it is about identifying the limitations of the Java type system which prevents the declaration of a Monad interface.
In my effort to understand monads I read this SO-answer by Eric Lippert on a question which asks about a simple explanation of monads. There, he also lists the operations which can be executed on a monad:
That there is a way to take a value of an unamplified type and turn it into a value of the amplified type.
That there is a way to transform operations on the unamplified type into operations on the amplified type that obeys the rules of functional composition mentioned before
That there is usually a way to get the unamplified type back out of the amplified type. (This last point isn't strictly necessary for a monad but it is frequently the case that such an operation exists.)
After reading more about monads, I identified the first operation as the return function and the second operation as the bind function. I was not able to find a commonly used name for the third operation, so I will just call it the unbox function.
To better understand monads, I went ahead and tried to declare a generic Monad interface in Java. For this, I first looked at the signatures of the three functions above. For the Monad M, it looks like this:
return :: T1 -> M<T1>
bind :: M<T1> -> (T1 -> M<T2>) -> M<T2>
unbox :: M<T1> -> T1
The return function is not executed on an instance of M, so it does not belong into the Monad interface. Instead, it will be implemented as a constructor or factory method.
Also for now, I omit the unbox function from the interface declaration, since it is not required. There will be different implementations of this function for the different implementations of the interface.
Thus, the Monad interface only contains the bind function.
Let's try to declare the interface:
public interface Monad {
Monad bind();
}
There are two flaws:
The bind function should return the concrete implementation, however it does only return the interface type. This is a problem, since we have the unbox operations declared on the concrete subtypes. I will refer to this as problem 1.
The bind function should retrieve a function as a parameter. We will address this later.
Using the concrete type in the interface declaration
This addresses problem 1: If my understanding of monads is correct, then the bind function always returns a new monad of the same concrete type as the monad where it was called on. So, if I have an implementation of the Monad interface called M, then M.bind will return another M but not a Monad. I can implement this using generics:
public interface Monad<M extends Monad<M>> {
M bind();
}
public class MonadImpl<M extends MonadImpl<M>> implements Monad<M> {
#Override
public M bind() { /* do stuff and return an instance of M */ }
}
At first, this seems to work, however there are at least two flaws with this:
This breaks down as soon as an implementing class does not provide itself but another implementation of the Monad interface as the type parameter M, because then the bind method will return the wrong type. For example the
public class FaultyMonad<M extends MonadImpl<M>> implements Monad<M> { ... }
will return an instance of MonadImpl where it should return an instance of FaultyMonad. However, we can specify this restriction in the documentation and consider such an implementation as a programmer error.
The second flaw is more difficult to resolve. I will call it problem 2: When I try to instantiate the class MonadImpl I need to provide the type of M. Lets try this:
new MonadImpl<MonadImpl<MonadImpl<MonadImpl<MonadImpl< ... >>>>>()
To get a valid type declaration, this has to go on infinitely. Here is another attempt:
public static <M extends MonadImpl<M>> MonadImpl<M> create() {
return new MonadImpl<M>();
}
While this seems to work, we just defered the problem to the called. Here is the only usage of that function that works for me:
public void createAndUseMonad() {
MonadImpl<?> monad = create();
// use monad
}
which essentially boils down to
MonadImpl<?> monad = new MonadImpl<>();
but this is clearly not what we want.
Using a type in its own declaration with shifted type parameters
Now, let's add the function parameter to the bind function: As described above, the signature of the bind function looks like this: T1 -> M<T2>. In Java, this is the type Function<T1, M<T2>>. Here is the first attempt to declare the interface with the parameter:
public interface Monad<T1, M extends Monad<?, ?>> {
M bind(Function<T1, M> function);
}
We have to add the type T1 as generic type parameter to the interface declaration, so we can use it in the function signature. The first ? is the T1 of the returned monad of type M. To replace it with T2, we have to add T2 itself as a generic type parameter:
public interface Monad<T1, M extends Monad<T2, ?, ?>,
T2> {
M bind(Function<T1, M> function);
}
Now, we get another problem. We added a third type parameter to the Monad interface, so we had to add a new ? to the usage of it. We will ignore the new ? for now to investigate the now first ?. It is the M of the returned monad of type M. Let's try to remove this ? by renaming M to M1 and by introducing another M2:
public interface Monad<T1, M1 extends Monad<T2, M2, ?, ?>,
T2, M2 extends Monad< ?, ?, ?, ?>> {
M1 bind(Function<T1, M1> function);
}
Introducing another T3 results in:
public interface Monad<T1, M1 extends Monad<T2, M2, T3, ?, ?>,
T2, M2 extends Monad<T3, ?, ?, ?, ?>,
T3> {
M1 bind(Function<T1, M1> function);
}
and introducing another M3 results in:
public interface Monad<T1, M1 extends Monad<T2, M2, T3, M3, ?, ?>,
T2, M2 extends Monad<T3, M3, ?, ?, ?, ?>,
T3, M3 extends Monad< ?, ?, ?, ?, ?, ?>> {
M1 bind(Function<T1, M1> function);
}
We see that this will go on forever if we try to resolve all ?. This is problem 3.
Summing it all up
We identified three problems:
Using the concrete type in the declaration of the abstract type.
Instantiating a type which receives itself as generic type parameter.
Declaring a type which uses itself in its declaration with shifted type parameters.
The question is: What is the feature that is missing in the Java type system? Since there are languages which work with monads, these languages have to somehow declare the Monad type. How do these other languages declare the Monad type? I was not able to find information about this. I only find information about the declaration of concrete monads, like the Maybe monad.
Did I miss anything? Can I properly solve one of these problems with the Java type system? If I cannot solve problem 2 with the Java type system, is there a reason why Java does not warn me about the not instantiable type declaration?
As already stated, this question is not about understanding monads. If my understanding of monads is wrong, you might give a hint about it, but don't attempt to give an explanation. If my understanding of monads is wrong the described problems remain.
This question is also not about whether it is possible to declare the Monad interface in Java. This question already received an answer by Eric Lippert in his SO-answer linked above: It is not. This question is about what exactly is the limitation that prevents me from doing this. Eric Lippert refers to this as higher types, but I can't get my head around them.
Most OOP languages do not have a rich enough type system to represent the monad pattern itself directly; you need a type system that supports types that are higher types than generic types. So I wouldn't try to do that. Rather, I would implement generic types that represent each monad, and implement methods that represent the three operations you need: turning a value into an amplified value, turning an amplified value into a value, and transforming a function on unamplified values into a function on amplified values.
What is the feature that is missing in the Java type system? How do these other languages declare the Monad type?
Good question!
Eric Lippert refers to this as higher types, but I can't get my head around them.
You are not alone. But they are actually not as crazy as they sound.
Let's answer both of your questions by looking at how Haskell declares the monad "type" -- you'll see why the quotes in a minute. I have simplified it somewhat; the standard monad pattern also has a couple other operations in Haskell:
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
return :: a -> m a
Boy, that looks both incredibly simple and completely opaque at the same time, doesn't it?
Here, let me simplify that a bit more. Haskell lets you declare your own infix operator for bind, but we'll just call it bind:
class Monad m where
bind :: m a -> (a -> m b) -> m b
return :: a -> m a
All right, now at least we can see that there are the two monad operations in there. What does the rest of this mean?
The first thing to get your head around, as you note, is "higher kinded types". (As Brian points out, I somewhat simplified this jargon in my original answer. Also quite amusing that your question attracted the attention of Brian!)
In Java, a "class" is a kind of "type", and a class may be generic. So in Java we've got int and IFrob and List<IBar> and they're all types.
From this point on throw away any intuition you have about Giraffe being a class that is a subclass of Animal, and so on; we won't need that. Think about a world with no inheritance; it will not come into this discussion again.
What are classes in Java? Well, the easiest way to think of a class is that it is a name for a set of values that have something in common, such that any one of those values can be used when an instance of the class is required. You have a class Point, lets say, and if you have a variable of type Point, you can assign any instance of Point to it. The Point class is in some sense just a way to describe the set of all Point instances. Classes are a thing that is higher than instances.
In Haskell there are also generic and non-generic types. A class in Haskell is not a kind of type. In Java, a class describes a set of values; any time you need an instance of the class, you can use a value of that type. In Haskell a class describes a set of types. That is the key feature that the Java type system is missing. In Haskell a class is higher than a type, which is higher than an instance. Java only has two levels of hierarchy; Haskell has three. In Haskell you can express the idea "any time I need a type that has certain operations, I can use a member of this class".
(ASIDE: I want to point out here that I am making a bit of an oversimplification . Consider in Java for example List<int> and List<String>. These are two "types", but Java considers them to be one "class", so in a sense Java also has classes which are "higher" than types. But then again, you could say the same in Haskell, that list x and list y are types, and that list is a thing that is higher than a type; it's a thing that can produce a type. So it would in fact be more accurate to say that Java has three levels, and Haskell has four. The point remains though: Haskell has a concept of describing the operations available on a type that is simply more powerful than Java has. We'll look at this in more detail below.)
So how is this different than interfaces? This sounds like interfaces in Java -- you need a type that has certain operations, you define an interface that describes those operations. We'll see what is missing from Java interfaces.
Now we can start making sense of this Haskell:
class Monad m where
So, what is Monad? It's a class. What is a class? It's a set of types that have something in common, such that whenever you need a type that has certain operations, you can use a Monad type.
Suppose we have a type that is a member of this class; call it m. What are the operations that must be on this type in order for that type to be a member of the class Monad?
bind :: m a -> (a -> m b) -> m b
return :: a -> m a
The name of the operation comes to the left of the ::, and the signature comes to the right. So to be a Monad, a type m must have two operations: bind and return. What are the signatures of those operations? Let's look at return first.
a -> m a
m a is Haskell for what in Java would be M<A>. That is, this means m is a generic type, a is a type, m a is m parametrized with a.
x -> y in Haskell is the syntax for "a function which takes type x and returns type y". It's Function<X, Y>.
Put it together, and we have return is a function that takes an argument of type a and returns a value of type m a. Or in Java
static <A> M<A> Return(A a);
bind is a little bit harder. I think the OP well understands this signature, but for readers who are unfamiliar with the terse Haskell syntax, let me expand on this a bit.
In Haskell, functions only take one argument. If you want a function of two arguments, you make a function that takes one argument and returns another function of one argument. So if you have
a -> b -> c
Then what have you got? A function that takes an a and returns a b -> c. So suppose you wanted to make a function that took two numbers and returned their sum. You would make a function that takes the first number, and returns a function that takes a second number and adds it to the first number.
In Java you'd say
static <A, B, C> Function<B, C> F(A a)
So if you wanted a C and you had and A and a B, you could say
F(a)(b)
Make sense?
All right, so
bind :: m a -> (a -> m b) -> m b
is effectively a function that takes two things: an m a, and a a -> m b and it returns an m b. Or, in Java, it is directly:
static <A, B> Function<Function<A, M<B>>, M<B>> Bind(M<A>)
Or, more idiomatically in Java:
static <A, B> M<B> Bind(M<A>, Function<A, M<B>>)
So now you see why Java cannot represent the monad type directly. It does not have the ability to say "I have a class of types that have this pattern in common".
Now, you can make all the monadic types you want in Java. The thing you can't do is make an interface that represents the idea "this type is a monad type". What you would need to do is something like:
typeinterface Monad<M>
{
static <A> M<A> Return(A a);
static <A, B> M<B> Bind(M<A> m, Function<A, M<B>> f);
}
See how the type interface talks about the generic type itself? A monadic type is any type M that is generic with one type parameter and has these two static methods. But you can't do that in the Java or C# type systems. Bind of course could be an instance method that takes an M<A> as this. But there is no way to make Return anything but static. Java gives you no ability to (1) parameterize an interface by an unconstructed generic type, and (2) no ability to specify that static members are part of the interface contract.
Since there are languages which work with monads, these languages have to somehow declare the Monad type.
Well you'd think so but actually not. First off, of course any language with a sufficient type system can define monadic types; you can define all the monadic types you want in C# or Java, you just can't say what they all have in common in the type system. You can't make a generic class that can only be parameterized by monadic types, for instance.
Second, you can embed the monad pattern in the language in other ways. C# has no way to say "this type matches the monad pattern", but C# has query comprehensions (LINQ) built into the language. Query comprehensions work on any monadic type! It's just that the bind operation has to be called SelectMany, which is a little weird. But if you look at the signature of SelectMany, you'll see that it is just bind:
static IEnumerable<R> SelectMany<S, R>(
IEnumerable<S> source,
Func<S, IEnumerable<R>> selector)
That's the implementation of SelectMany for the sequence monad, IEnumerable<T>, but in C# if you write
from x in a from y in b select z
then a's type can be of any monadic type, not just IEnumerable<T>. What is required is that a is M<A>, that b is M<B>, and that there is a suitable SelectMany that follows the monad pattern. So that's another way of embedding a "monad recognizer" in the language, without representing it directly in the type system.
(The previous paragraph is actually a lie of oversimplification; the binding pattern used by this query is slightly different than the standard monadic bind for performance reasons. Conceptually this recognizes the monad pattern; in actuality the details differ slightly. Read about them here http://ericlippert.com/2013/04/02/monads-part-twelve/ if you're interested.)
A few more small points:
I was not able to find a commonly used name for the third operation, so I will just call it the unbox function.
Good choice; it is usually called the "extract" operation. A monad need not have an extract operation exposed, but of course somehow bind needs to be able to get the A out of the M<A> in order to call the Function<A, M<B>> on it, so logically some sort of extraction operation usually exists.
A comonad -- a backwards monad, in a sense -- requires an extract operation to be exposed; extract is essentially return backwards. A comonad as well requires an extend operation that is sort of bind turned backwards. It has the signature static M<B> Extend(M<A> m, Func<M<A>, B> f)
If you look at what the AspectJ project is doing, it is similar to applying monads to Java. The way they do it is to post-process the byte code of the classes to add the additional functionality-- and the reason they have to do that is because there is no way within the language without the AspectJ extensions to do what they need to do; the language is not expressive enough.
A concrete example: say you start with class A. You have a monad M such that M(A) is a class that works just like A, but all method entrances and exits get traced to log4j. AspectJ can do this, but there is no facility within the Java language itself that would let you.
This paper describes how Aspect-Oriented Programming as in AspectJ might be formalized as monads
In particular, there is no way within the Java language to specify a type programmatically (short of byte-code manipulation a la AspectJ). All types are pre-defined when the program starts.
Good question indeed! :-)
As #EricLippert pointed out, the type of polymorphism that is known as "type classes" in Haskell is beyond the grasp of Java's type system. However, at least since the introduction of the Frege programming language it has been shown that a Haskell-like type system can indeed be implemented on top of the JVM.
If you want to use higher-kinded types in the Java language itself you have to resort to libraries like highJ or Cyclops. Both libraries do provide a monad type class in the Haskell sense (see here and here, respectively, for the sources of the monad type class). In both cases, be prepared for some major syntactic inconveniences; this code will not look pretty at all and carries a lot of overhead to shoehorn this functionality into Java's type system. Both libraries use a "type witness" to capture the core type separately from the data type, as John McClean explains in his excellent introduction. However, in neither implementation you will find anything as simple and straightforward as Maybe extends Monad or List extends Monad.
The secondary problem of specifying constructors or static methods with Java interfaces can be easily overcome by introducing a factory (or "companion") interface that declares the static method as a non-static one. Personally, I always try to avoid anything static and use injected singletons instead.
Long story short, yes, it is possible to represent HKTs in Java but at this point it is very inconvenient and not very user friendly.
Yes, we cannot override static method in class, and we cannot write constructor in interface.
use abstract class to simulate Monad type class in Haskell
import java.util.function.Function;
public abstract class Monad<T> {
public static <T> Monad<T> Unit(T a){
throw new UnsupportedOperationException("Call Unit in abstract class: Monad");
}
public <R> Monad<R> OUnit(R a){
throw new UnsupportedOperationException("Call OUnit in abstract class: Monad");
}
public <B> Monad<B> bind(Function<T, Monad<B>> func){
throw new UnsupportedOperationException("Call bind in abstract class: Monad");
}
public <B> Monad<B> combine(Monad<B> b){
return this.bind(unused -> b);
}
}
public class Maybe<T> extends Monad<T> {
public boolean has;
public T val;
public Maybe(T value) {
this.has = true;
this.val = value;
}
public Maybe(){
has = false;
}
public static <T> Maybe<T> Unit(T a) {
return new Maybe<T>(a);
}
public static <T> Maybe<T> Unit() {
return new Maybe<T>();
}
#Override
public <R> Maybe<R> OUnit(R a) {
return new Maybe<R>(a);
}
public <T> Maybe<T> OUnit() {
return new Maybe<T>();
}
#Override
public <B> Monad<B> bind(Function<T, Monad<B>> func){
if (this.has){
return func.apply(this.val);
}
return new Maybe<B>();
}
#Override
public String toString(){
if (this.has){
return "Maybe " + val.toString();
}
return "Nothing";
}
}
public class Main {
/*
example :: (Monad m, Show (m n), Num n) => m n -> m n -> IO ()
example a b = do
print $ a >> b
print $ b >> a
print $ a >>= (\x -> return $ x+x)
print $ b >>= (\x -> return $ x+x)
main = do
example (Just 10) (Just 5)
example (Right 10) (Left 5)
*/
public static void example(Monad<Integer> a, Monad<Integer> b){
System.out.println(a.bind(x -> b));
System.out.println(b.bind(x -> b));
System.out.println(a.bind(x -> a.OUnit(x*2)));
System.out.println(b.bind(x -> b.OUnit(x*2)));
System.out.println(a.combine(a));
System.out.println(a.combine(b));
System.out.println(b.combine(a));
System.out.println(b.combine(b));
}
// Monad can also used in any Objects
public static void example2(Monad<Object> a, Monad<Object> b){
System.out.println(a.bind(x -> b));
System.out.println(b.bind(x -> b));
System.out.println(a.combine(a));
System.out.println(a.combine(b));
System.out.println(b.combine(a));
System.out.println(b.combine(b));
}
public static void main(String[] args){
System.out.println("Example 1:");
example(Maybe.<Integer>Unit(10), Maybe.<Integer>Unit());
System.out.println("\n\nExample 2:");
example(Maybe.<Integer>Unit(1), Maybe.<Integer>Unit(3));
System.out.println("\n\nExample 3:");
example2(Maybe.<Object>Unit(10), Maybe.<Object>Unit());
}
}
use interface to simulate Monad type class in Haskell
import java.util.function.Function;
public interface Monad<T> {
public static <T> Monad<T> Unit(T a){
throw new UnsupportedOperationException("call Unit in Monad interface");
}
public <R> Monad<R> OUnit(R a);
public <B> Monad<B> bind(Function<T, Monad<B>> func);
default public <B> Monad<B> combine(Monad<B> b){
return bind(x-> b);
};
}
// in class Maybe, replace extends with implements
// in class Main, unchanged
and the output is the same

Java 8 needs a cast while Java 7 didn't - enum.getClass/getDeclaringClass

I realise Java 8 is still in Beta but this one struck me as odd:
public class Fields<C extends Enum<C>> {
public Fields(Set<C> columns) {
// A sample column used to find the universe of the enum of Columns.
C sampleCol = columns.iterator().next();
// Java 8 needs a cast here.
Set<C> allColumns = EnumSet.allOf((/*Class<C>)*/ sampleCol.getClass());
// ... there's more to this that I've deleted.
}
}
The error reads:
error: incompatible types: inferred type does not conform to equality constraint(s)
Set<C> allColumns = EnumSet.allOf(sampleCol.getClass());
inferred: C
equality constraints(s): C,CAP#1
where C is a type-variable:
C extends Enum<C> declared in class Test.Fields
where CAP#1 is a fresh type-variable:
CAP#1 extends Enum from capture of ? extends Enum
Is this a bug or a new feature of Java 8?
Interesting, this is a subtle change in the treatment of raw types.
First, let's clarify your example. The return type of Object.getClass is special:
The actual result type is Class<? extends |X|> where |X| is the erasure of the static type of the expression on which getClass is called.
In this case, X would be the type parameter C, which erases to Enum. So sampleCol.getClass() returns Class<? extends Enum>. EnumSet.allOf declares the type parameter E extends Enum<E>, and in your case ? extends Enum is being inferred as its type argument.
The important part is that Enum is a raw type. The use of raw types has been seen to erase seemingly unrelated generics, for example on this post: Why won't this generic java code compile? In his answer there, Jon Skeet cites JLS §4.8 ("Raw Types") to cover this unintuitive behavior.
Similar behavior seems to be happening in your example with Java 7: EnumSet.allOf(sampleCol.getClass()) is allowed to compile with an "unchecked invocation" warning (this gets hidden by the subsequent "unchecked conversion" warning from assigning the resulting raw EnumSet to Set<C>).
The question becomes: should the occurrence of a raw type in a generic wildcard's bounds allow unchecked conversions? JLS §4.8 makes no mention of this, so it's ambiguous. Possibly it's a bug, but it seems like a reasonable tightening of this behavior. While a standard raw type like Enum might itself be expected from legacy APIs, a "half-baked" type like Class<? extends Enum> could only occur post-generics and so it doesn't really make sense to let it disrupt generic type checking.
Anyway I'm interested to see if anyone can point to documentation about this change - my search didn't turn anything up.
About your specific code: you should use getDeclaringClass() instead. The compiler can't know that calling getClass on a C will return exactly Class<C>; in fact, it won't if used on an enum with a constant-specific class. This is exactly the use case for which Enum declares that method.

Invariance, covariance and contravariance in Java

Java lesson on generics are leading me to variance concept. This causes me some headaches as I cannot find a very simple demonstration of what it is.
I have read several similar questions on stackoverflow, but I found them too difficult to understand for a Java learner. Actually the problem is that the explanation of generics requires variance to be understood, and the concept of variance is demonstrated relying heavily on generics understanding.
I had some hope reading this, but in the end I shared C. R.'s feeling:
The title reminds me of the days learning general relativity. – C.R.
Dec 22 '13 at 7:34
Four theory questions are very confusing to me, and I cannot find good and simple explanations. Here they are, with my current partial understanding (I fear experts will have a great fun reading this).
Your help to correct and clarify is welcome (remember this is for beginners, not for experts).
Is there something wrong with this understanding?
What is invariance / covariance / contravariance related to in the context of programing? My best guess is that:
This is something encountered in object-oriented programing.
This has to do when looking at method arguments and result type in the class and an ancestor.
This is used in the context of method overriding and overloading.
This is used to establish a connection between the type of a method argument, or the method return type, and the inheritance of the classes themselves, e.g. if class D is a descendant of class A, what can we say about the types of arguments and the method method return type?
How variance relates to Java methods? My best guess is that, given two classes A and D, with A being an ancestor of D, and a overhiden/overloaded method f(arg):
If the relation between the argument type in the two methods IS THE SAME than the relation between the two classes, the argument type in the method is said COVARIANT with the class type, said otherwise: the inheritance between arg types in A and D is covariant with the inheritance of classes A and D.
If the relation between the arguments REVERSES the relation between classes, the arg type is said CONTRAVARIANT to the class type, said otherwise: the inheritance between arg types in A and D is contravariant with the inheritance of classes A and D..
Why is variance understanding so important for Java programmers? My guess is that:
Java language creators have implemented rules for variance in the language, and this has implications on what a programmer can do.
A rule states that the return type of an overriding/overloading method must be contravariant to the inheritance.
Another rule states that the type of an argument of an overriding/overloading must be is covariant to the inheritance.
The Java compiler checks the variance rules are valid, and provides errors or warnings accordingly. Deciphering the messages is easier with variance knowledge.
What is the difference between overrhiding and overloading? Best guess:
A method overrides another method when argument and return types are both invariant. All other cases are understood by the compiler as overloading.
This is not specific to OO, but has to do with the properties of certain types.
For example, with the function type
A -> B // functional notation
public B meth(A arg) // how this looks in Java
we have the following:
Let C be a subtype of A, and D be a subtype of B. Then the following is valid:
B b = meth(new C()); // B >= B, C < A
Object o = meth(new C()); // Object > B, C < A
but the follwoing are invalid:
D d = meth(new A()); // because D < B
B b = meth(new Object()); // because Object > A
hence, to check whether a call of meth is valid, we must check
The expected return type is a supertype of the declared return type.
The actual argument type is a subtype of the declared argument type.
This is all well known and intuitive. By convention we say that the return type of a function is covariant, and the argument type of a method is contravariant.
With parameterized types, like List, we have it that the argument type is invariant in languages like Java, where we have mutability. We can't say that a list of C's is a list of A's, because, if it were so, we could store an A in a list of Cs, much to the surprise of the caller, who assumes only Cs in the list. However, in languages where values are immutable, like Haskell, this is not a problem. Because the data we pass to functions cannot be mutated, a list of C actually is a list of A if C is a subtype of A. (Note that Haskell has no real subtyping, but has instead the related notion of "more/less polymorphic" types.)

Forward Reference of Type Parameter in Java Generics

According to Java Generics FAQ
http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#FAQ302
a type parameter cannot be forward-referenced in this way
<A extends B, B> // error
but it is ok to have
<A extends List<B>, B> // ok
These two examples are verified with the latest jdk 1.6.0_24.
My question is, where in the language spec this is specified, implied, or deductible(i.e. if it is untrue, other things can blow up). I can't find it anywhere.
Update
In javac7, it is allowed. Intuitively, the order of type parameters doesn't matter; the type system requires that there's no cyclic dependencies among type variables: <A extends B, B extends A>. Previously, this can be guaranteed by forbidding forward reference. Apparently javac 7 is improved to relax the ordering, while detecting cycles regardless of ordering.
I'm not sure this is true. I looked over the Java Language Specification and in §6.3 there's this discussion of the scopes of type parameters:
The scope of an interface's type parameter is the entire declaration of the interface including the type parameter section itself. Therefore, type parameters can appear as parts of their own bounds, or as bounds of other type parameters declared in the same section.
The scope of a method's type parameter is the entire declaration of the method, including the type parameter section itself. Therefore, type parameters can appear as parts of their own bounds, or as bounds of other type parameters declared in the same section.
The scope of a constructor's type parameter is the entire declaration of the constructor, including the type parameter section itself. Therefore, type parameters can appear as parts of their own bounds, or as bounds of other type parameters declared in the same section.
(My emphasis).
This suggests that in the declaration
that B is indeed in scope when writing A extends B.
Furthermore, §4.4 of the JLS says, when referring to the bound on a type variable, that
The bound consists of either a type variable, or a class or interface type T
Which suggests that not only is B in scope in <A extends B, B>, but that it's a perfectly legal bound on A.
Finally, to top things off, this code compiles in javac:
public class Test {
public static <A extends B, B> A test(B obj) {
return null;
}
}
So I'm pretty sure that this is perfectly legal Java code and that the example you've linked to is either wrong or is referring to something else.
Hope this helps, and let me know if there's a flaw in my reasoning!
It is completely legal, say more, you can imagine that A extends C which is generally extends B.
So what would you say about when C extends B?

Categories

Resources