Empty value types

Paul Govereau paul.govereau at oracle.com
Tue Aug 5 18:56:28 UTC 2014

Ok, that makes sense. You are saying we should treat what I was calling 
an "empty value type" as a unit type instead. That is, a type with 
exactly one member, and not a void type like I was thinking (which has 
zero members). Also, if we think about value types in general as named 
tuples, then the empty tuple is naturally a unit.

This raises another question though: what about void? There are several 
uses of the type java.lang.Void in the libraries. The way I read these, 
what is wanted is an analog of "void": that is, a truly empty type, not 
a unit type (otherwise it would be called java.lang.Unit?). Given this, 
should we have a way to declare analogs of "void"?

   final __ByValue class LikeUnit { }

   final __ByValue class LikeInt { int x; }

   final __ByValue class LikeVoid { ????? }

Relatedly, is this a valid declaration:

   final __ByValue V<T extends V<T>> { T t; }

and what is its relation to LikeVoid given that T is provably empty (has 
no members)?

Another related question is: can we instantiate generic types with 
"void"? e.g.

   class F implements Function<int,void> {
     void apply(int x) { ... }


   Set<void> one;

In some sense, we are promoting the primitive types up to being 
first-class citizens in the language: they can be user defined as value 
types, used in generics, etc. Is void coming along for the ride?

My guess is no, the examples above are all illegal: void has no 
user-defined analogs, values can't be parametrized by empty types, and 
void can't be used to instantiate a generic type. Is this right, or do 
we want to think about making void a first-class citizen along with int, 


PS: In other languages we can see first-class void types, like:

  type Void
  type Unit = ()
  type Option a = Some a | None
  type AnotherUnit = Option Void

However, the language must guarantee that no value of a void type can 
ever appear in a term.

On 08/05/2014 01:04 AM, John Rose wrote:
> Empty value types are perfectly reasonable to instantiate, although there is only one value of each such type (1 = 2^0).
> A type Set<T> can be efficiently implemented as Map<T,Unit>, if Unit is an empty value type which is instantiated for each set element.
> It is true that static members of empty types are not interestingly different from non static members. But I don't see a reason to forbid one or the other. If the type implements an interface it needs non static methods. Factories are static. Seems we need both even for the empties.
> Lots of types in FP langs use a unit type, and corresponding unit values, at least for arrow types. Am I missing something here?
> – John
>> On Aug 1, 2014, at 10:05 AM, Paul Govereau <paul.govereau at oracle.com> wrote:
>> I don't think there is anything wrong with it. I can even think of a use case: phantom types.
>> final __ByValue class ReadWrite {}
>> final __ByValue class ReadOnly {}
>> final __ByValue class File<T> { ... }
>> File<ReadWrite> openForWrite(String file) { ... }
>> File<ReadOnly>  openForRead(String file) { ... }
>> void write(File<ReadWrite> file, ...) { ... }
>> However, I think we need to add checks to detect construction of empty value types. I am not sure what to do about methods defined inside of an empty type? Maybe only static methods are OK?
>> Paul
>>> On 08/01/2014 12:50 PM, Brian Goetz wrote:
>>> While an empty value is silly, is there something actually wrong with it?
>>> Sent from my iPhone
>>>> On Aug 1, 2014, at 9:47 AM, Paul Govereau <paul.govereau at oracle.com> wrote:
>>>> What are we going to do with empty value types?
>>>> The most sensible thing seems to allow them to be declared but not constructed. e.g.
>>>>   final __ByValue class Void {}   // <- ok
>>>>   Void v = __Make Void();   // <- error cannot construct empty type.
>>>> Paul

More information about the valhalla-dev mailing list