This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Union types

10 replies
Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.

hi,

I wanted to put an idea in the round that came up in a comment of a stackoverflow entry ( http://stackoverflow.com/questions/5645700/whats-the-difference-between-... ):

We have a sort of type intersection in the form of `A with B`, so that in

def perform( x: A with B ) { ... }

we can assume the functionality of both types `A` and `B`. Wouldn't it be a very interesting idea to explore the possibility of a type *union*, like

def perform( x: A or B ) { ... }

so that the main body of that method can safely invoke anything on `x` which is common between types `A` and `B`. It would then be possible to do an exhaustive match like this:

def perform( x: A or B ) {
...
x match {
case a: A => ...
case b: B => ...
}
}

and that way in some distant version of Scala one would overcome the need to have method overloading and multiple constructors.

Although we will hopefully in this distant version have fully supported runtime generics, this could also solve the case of

def perform( a: List[ A ]) { ... }
def perform( b: List[ B ]) { ... }

under the condition that erasure is still happening, because then you could do

def perform( a: List[ A or B ]) { ... }

i know there is `Either` but that has many disadvantages against this union types -- it is extra verbose, cannot handle view bounds on its type parameters without much extra bloat of implicits work, and it cannot handle more than two types.

best, -sciss-

extempore
Joined: 2008-12-17,
User offline. Last seen 35 weeks 3 days ago.
Re: Union types

On 4/15/11 9:00 AM, Sciss wrote:
> we can assume the functionality of both types `A` and `B`. Wouldn't it be a very interesting idea to explore the possibility of a type *union*, like
>
> def perform( x: A or B ) { ... }

https://lampsvn.epfl.ch/trac/scala/ticket/3749

"We plan to address this issue in future versions of Scala by
introducing union types, so that the approximation of the least upper
bound you see here could be denoted directly (and precisely) as
java.lang.Double or java.lang.Long. [...]

First, we need to work out the nitty gritty details of the theory, though."

Chris Twiner
Joined: 2008-12-17,
User offline. Last seen 42 years 45 weeks ago.
Re: Union types

How often would you use that where the more general structural types wouldn't work?

On 15 Apr 2011 18:00, "Sciss" <contact@sciss.de> wrote:

hi,

I wanted to put an idea in the round that came up in a comment of a stackoverflow entry ( http://stackoverflow.com/questions/5645700/whats-the-difference-between-scala-and-red-hats-ceylon-language/5646305#comment-6468943 ):

We have a sort of type intersection in the form of `A with B`, so that in

   def perform( x: A with B ) { ... }

we can assume the functionality of both types `A` and `B`. Wouldn't it be a very interesting idea to explore the possibility of a type *union*, like

   def perform( x: A or B ) { ... }

so that the main body of that method can safely invoke anything on `x` which is common between types `A` and `B`. It would then be possible to do an exhaustive match like this:

    def perform( x: A or B ) {
      ...
      x match {
         case a: A => ...
         case b: B => ...
      }
   }

and that way in some distant version of Scala one would overcome the need to have method overloading and multiple constructors.

Although we will hopefully in this distant version have fully supported runtime generics, this could also solve the case of

   def perform( a: List[ A ]) { ... }
   def perform( b: List[ B ]) { ... }

under the condition that erasure is still happening, because then you could do

   def perform( a: List[ A or B ]) { ... }

i know there is `Either` but that has many disadvantages against this union types -- it is extra verbose, cannot handle view bounds on its type parameters without much extra bloat of implicits work, and it cannot handle more than two types.

best, -sciss-

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Union types

note that A and B do not necessarily have any substantial common interface! the pattern matching example below is exactly where union types would fit in and structural types clearly not.

On 15 Apr 2011, at 17:13, Chris Twiner wrote:

> How often would you use that where the more general structural types wouldn't work?
>
>
>> On 15 Apr 2011 18:00, "Sciss" wrote:
>>
>> hi,
>>
>> I wanted to put an idea in the round that came up in a comment of a stackoverflow entry ( http://stackoverflow.com/questions/5645700/whats-the-difference-between-... ):
>>
>> We have a sort of type intersection in the form of `A with B`, so that in
>>
>> def perform( x: A with B ) { ... }
>>
>> we can assume the functionality of both types `A` and `B`. Wouldn't it be a very interesting idea to explore the possibility of a type *union*, like
>>
>> def perform( x: A or B ) { ... }
>>
>> so that the main body of that method can safely invoke anything on `x` which is common between types `A` and `B`. It would then be possible to do an exhaustive match like this:
>>
>> def perform( x: A or B ) {
>> ...
>> x match {
>> case a: A => ...
>> case b: B => ...
>> }
>> }
>>
>> and that way in some distant version of Scala one would overcome the need to have method overloading and multiple constructors.
>>
>> Although we will hopefully in this distant version have fully supported runtime generics, this could also solve the case of
>>
>> def perform( a: List[ A ]) { ... }
>> def perform( b: List[ B ]) { ... }
>>
>> under the condition that erasure is still happening, because then you could do
>>
>> def perform( a: List[ A or B ]) { ... }
>>
>> i know there is `Either` but that has many disadvantages against this union types -- it is extra verbose, cannot handle view bounds on its type parameters without much extra bloat of implicits work, and it cannot handle more than two types.
>>
>> best, -sciss-
>>
>

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Union types

Hooray !!!

`List(1.0, 2)` by the way is a good example of where this could be extremely useful, too.

best, -sciss-

On 15 Apr 2011, at 17:12, Paul Phillips wrote:

> On 4/15/11 9:00 AM, Sciss wrote:
>> we can assume the functionality of both types `A` and `B`. Wouldn't it be a very interesting idea to explore the possibility of a type *union*, like
>>
>> def perform( x: A or B ) { ... }
>
> https://lampsvn.epfl.ch/trac/scala/ticket/3749
>
> "We plan to address this issue in future versions of Scala by introducing union types, so that the approximation of the least upper bound you see here could be denoted directly (and precisely) as java.lang.Double or java.lang.Long. [...]
>
> First, we need to work out the nitty gritty details of the theory, though."

Jim McBeath
Joined: 2009-01-02,
User offline. Last seen 42 years 45 weeks ago.
Re: Union types

Mitch Blevins implements this in his blog entry "Stuttering Or":
http://cleverlytitled.blogspot.com/2009/03/so-i-read-both-jim-mcbeath-an...

--
Jim

On Fri, Apr 15, 2011 at 05:00:30PM +0100, Sciss wrote:
> Date: Fri, 15 Apr 2011 17:00:30 +0100
> From: Sciss
> To: scala-language@googlegroups.com
> Subject: [scala-language] Union types
>
> hi,
>
> I wanted to put an idea in the round that came up in a comment of a stackoverflow entry ( http://stackoverflow.com/questions/5645700/whats-the-difference-between-... ):
>
> We have a sort of type intersection in the form of `A with B`, so that in
>
> def perform( x: A with B ) { ... }
>
> we can assume the functionality of both types `A` and `B`. Wouldn't it be a very interesting idea to explore the possibility of a type *union*, like
>
> def perform( x: A or B ) { ... }
>
> so that the main body of that method can safely invoke anything on `x` which is common between types `A` and `B`. It would then be possible to do an exhaustive match like this:
>
> def perform( x: A or B ) {
> ...
> x match {
> case a: A => ...
> case b: B => ...
> }
> }
>
> and that way in some distant version of Scala one would overcome the need to have method overloading and multiple constructors.
>
> Although we will hopefully in this distant version have fully supported runtime generics, this could also solve the case of
>
> def perform( a: List[ A ]) { ... }
> def perform( b: List[ B ]) { ... }
>
> under the condition that erasure is still happening, because then you could do
>
> def perform( a: List[ A or B ]) { ... }
>
> i know there is `Either` but that has many disadvantages against this union types -- it is extra verbose, cannot handle view bounds on its type parameters without much extra bloat of implicits work, and it cannot handle more than two types.
>
> best, -sciss-
>

Sciss
Joined: 2008-12-17,
User offline. Last seen 28 weeks 5 days ago.
Re: Union types

very neat!

the only downsides are that the compiler cannot check the matches for exhaustiveness, that i cannot use common interface between the types, and that you need to import half a dozen imports (that always makes me slightly depressed and i think this is an example of why people keep having the impression that scala is too complicated).

best, -sciss-

On 15 Apr 2011, at 17:23, Jim McBeath wrote:

> Mitch Blevins implements this in his blog entry "Stuttering Or":
> http://cleverlytitled.blogspot.com/2009/03/so-i-read-both-jim-mcbeath-an...
>
> --
> Jim
>
> On Fri, Apr 15, 2011 at 05:00:30PM +0100, Sciss wrote:
>> Date: Fri, 15 Apr 2011 17:00:30 +0100
>> From: Sciss
>> To: scala-language@googlegroups.com
>> Subject: [scala-language] Union types
>>
>> hi,
>>
>> I wanted to put an idea in the round that came up in a comment of a stackoverflow entry ( http://stackoverflow.com/questions/5645700/whats-the-difference-between-... ):
>>
>> We have a sort of type intersection in the form of `A with B`, so that in
>>
>> def perform( x: A with B ) { ... }
>>
>> we can assume the functionality of both types `A` and `B`. Wouldn't it be a very interesting idea to explore the possibility of a type *union*, like
>>
>> def perform( x: A or B ) { ... }
>>
>> so that the main body of that method can safely invoke anything on `x` which is common between types `A` and `B`. It would then be possible to do an exhaustive match like this:
>>
>> def perform( x: A or B ) {
>> ...
>> x match {
>> case a: A => ...
>> case b: B => ...
>> }
>> }
>>
>> and that way in some distant version of Scala one would overcome the need to have method overloading and multiple constructors.
>>
>> Although we will hopefully in this distant version have fully supported runtime generics, this could also solve the case of
>>
>> def perform( a: List[ A ]) { ... }
>> def perform( b: List[ B ]) { ... }
>>
>> under the condition that erasure is still happening, because then you could do
>>
>> def perform( a: List[ A or B ]) { ... }
>>
>> i know there is `Either` but that has many disadvantages against this union types -- it is extra verbose, cannot handle view bounds on its type parameters without much extra bloat of implicits work, and it cannot handle more than two types.
>>
>> best, -sciss-
>>

Randall R Schulz
Joined: 2008-12-16,
User offline. Last seen 1 year 29 weeks ago.
Re: Union types

On Friday April 15 2011, Paul Phillips wrote:
> On 4/15/11 9:00 AM, Sciss wrote:
> > we can assume the functionality of both types `A` and `B`. Wouldn't
> > it be a very interesting idea to explore the possibility of a type
> > *union*, like
> >
> > def perform( x: A or B ) { ... }
>
> https://lampsvn.epfl.ch/trac/scala/ticket/3749
>
> "We plan to address this issue in future versions of Scala by
> introducing union types, so that the approximation of the least upper
> bound you see here could be denoted directly (and precisely) as
> java.lang.Double or java.lang.Long. [...]

The LUB of two arbitrary types will in general subsume many types that
would not otherwise be compatible with either of the two original
types, so this does not seem to me like a proper interpretation of the
union of two types.

> First, we need to work out the nitty gritty details of the theory,
> though."

Randall Schulz

vpatryshev
Joined: 2009-02-16,
User offline. Last seen 1 year 24 weeks ago.
Re: Union types
Thanks; curious, familiar technique: building colimits in toposes (Mikkelsen, Pare)


On Fri, Apr 15, 2011 at 9:23 AM, Jim McBeath <scala@j.jimmc.org> wrote:
Mitch Blevins implements this in his blog entry "Stuttering Or":
http://cleverlytitled.blogspot.com/2009/03/so-i-read-both-jim-mcbeath-and-michids.html

--
Jim

On Fri, Apr 15, 2011 at 05:00:30PM +0100, Sciss wrote:
> Date: Fri, 15 Apr 2011 17:00:30 +0100
> From: Sciss <contact@sciss.de>
> To: scala-language@googlegroups.com
> Subject: [scala-language] Union types
>
> hi,
>
> I wanted to put an idea in the round that came up in a comment of a stackoverflow entry ( http://stackoverflow.com/questions/5645700/whats-the-difference-between-scala-and-red-hats-ceylon-language/5646305#comment-6468943 ):
>
> We have a sort of type intersection in the form of `A with B`, so that in
>
>     def perform( x: A with B ) { ... }
>
> we can assume the functionality of both types `A` and `B`. Wouldn't it be a very interesting idea to explore the possibility of a type *union*, like
>
>     def perform( x: A or B ) { ... }
>
> so that the main body of that method can safely invoke anything on `x` which is common between types `A` and `B`. It would then be possible to do an exhaustive match like this:
>
>      def perform( x: A or B ) {
>        ...
>        x match {
>           case a: A => ...
>           case b: B => ...
>        }
>     }
>
> and that way in some distant version of Scala one would overcome the need to have method overloading and multiple constructors.
>
> Although we will hopefully in this distant version have fully supported runtime generics, this could also solve the case of
>
>     def perform( a: List[ A ]) { ... }
>     def perform( b: List[ B ]) { ... }
>
> under the condition that erasure is still happening, because then you could do
>
>     def perform( a: List[ A or B ]) { ... }
>
> i know there is `Either` but that has many disadvantages against this union types -- it is extra verbose, cannot handle view bounds on its type parameters without much extra bloat of implicits work, and it cannot handle more than two types.
>
> best, -sciss-
>

Ben Hutchison
Joined: 2009-01-21,
User offline. Last seen 42 years 45 weeks ago.
Re: Union types

FWIW, I was wanting the same capability myself last week, to address
the difficulty of overloading methods by parameter type, when the
types are parametrized.

I often find myself wanting an API to respond to several related
parametrized types. Some common examples:

aMethod(t: T)
aMethod(optT: Option[T])
aMethod(ts: Seq[T])

It would be nice to support this without requiring implicit conversions.

-Ben

On Sat, Apr 16, 2011 at 2:00 AM, Sciss wrote:
Wouldn't it be a very interesting idea to explore the possibility of a
type *union*, like
>
>    def perform( x: A or B ) { ... }
>
> so that the main body of that method can safely invoke anything on `x` which is common between types `A` and `B`. It would then be possible to do an exhaustive match like this:
>
>     def perform( x: A or B ) {
>       ...
>       x match {
>          case a: A => ...
>          case b: B => ...
>       }
>    }
>
> and that way in some distant version of Scala one would overcome the need to have method overloading and multiple constructors.

Alex Repain
Joined: 2010-07-27,
User offline. Last seen 1 year 31 weeks ago.
Re: Union types


2011/4/18 Ben Hutchison <ben@playscapegames.com>
FWIW, I was wanting the same capability myself last week, to address
the difficulty of overloading methods by parameter type, when the
types are parametrized.

I often find myself wanting an API to respond to several related
parametrized types. Some common examples:

aMethod(t: T)
aMethod(optT: Option[T])
aMethod(ts: Seq[T])

It would be nice to support this without requiring implicit conversions.

Not exactly the same problem. What you want is syntactic sugar to  port some methods to container types, but that is not exactly what union types would create. Union types would allow you to do

aMethod(a: A or Option[A]) : B

which is somehow equivalent to what you're looking for. This example can clearly be desugared to :

aMethod(a: A) : B
aMethod(Option[A]) : B

I personnally think that implicits are the right way to go for that case.
Union types would also allow you to do :

anotherMethod(abs: Seq[A or B]) : C

or even stranger :

another method(a: A) : B or C

which means that the Seq requested as parameter would contain potentially A instances and B instances at same time. The problem is more complex and as Martin said, I think the integration of such thing in Scala has to be studied first, to check it doesn't break the coherence of the type system.


-Ben

On Sat, Apr 16, 2011 at 2:00 AM, Sciss <contact@sciss.de> wrote:
Wouldn't it be a very interesting idea to explore the possibility of a
type *union*, like
>
>    def perform( x: A or B ) { ... }
>
> so that the main body of that method can safely invoke anything on `x` which is common between types `A` and `B`. It would then be possible to do an exhaustive match like this:
>
>     def perform( x: A or B ) {
>       ...
>       x match {
>          case a: A => ...
>          case b: B => ...
>       }
>    }
>
> and that way in some distant version of Scala one would overcome the need to have method overloading and multiple constructors.

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland