Why aren't there anonymous sum types in Haskell?

A tuple is basically an anonymous product type. It's convenient to not have to spend the time making a named product type, because product types are so obviously useful. Is there any reason why Haskell doesn't have anonymous sum types? If there isn't some theoretical problem, is there any practical reason why they haven't been implemented? It seems to me that type inference on anonymous sum types would give you a lot of the power that you get from heterogeneous lists. Whenever you use a heterogeneous list, you've essentially got a homogenous list of some sum type. If you don't handle all of the cases of the sum type, then you're going to eventually run into a type error. It seems to me that having type inference on anonymous sums would allow you to safely get the power of a heterogeneous list. Am I missing something here, or is this correct?

On 21 Jun 2011, at 20:53, Elliot Stern wrote:
A tuple is basically an anonymous product type. It's convenient to not have to spend the time making a named product type, because product types are so obviously useful.
Is there any reason why Haskell doesn't have anonymous sum types? If there isn't some theoretical problem, is there any practical reason why they haven't been implemented?
The Either type is the nearest Haskell comes to having anonymous sum types. If you are bothered because Either has a name and constructors, it does not take long before you realise that (,) has a name and a constructor too. Regards, Malcolm

On Jun 21, 2011, at 4:02 PM, Malcolm Wallace wrote:
On 21 Jun 2011, at 20:53, Elliot Stern wrote:
A tuple is basically an anonymous product type. It's convenient to not have to spend the time making a named product type, because product types are so obviously useful.
Is there any reason why Haskell doesn't have anonymous sum types? If there isn't some theoretical problem, is there any practical reason why they haven't been implemented?
The Either type is the nearest Haskell comes to having anonymous sum types.
If you are bothered because Either has a name and constructors, it does not take long before you realise that (,) has a name and a constructor too.
Yes, Either is to sum types what (,) is to product types. The difference is that there is no "anonymous" sum type equivalent to (,,) and (,,,) and (,,,,) and so on, which I think is what the original question is getting at. Indeed, I sometimes wish I could write something like (straw-man syntax): foo :: (Int | Bool | String | Double) -> Int foo x = case x of 1stOf4 i -> i + 7 2ndOf4 b -> if b then 1 else 0 3rdOf4 s -> length s 4thOf4 d -> floor d bar :: Int bar = foo (2ndOf4 True) and have that work for any size of sum type. But I can't. Cheers, -Matt

On Tue, Jun 21, 2011 at 1:36 PM, Matthew Steele
On Jun 21, 2011, at 4:02 PM, Malcolm Wallace wrote:
On 21 Jun 2011, at 20:53, Elliot Stern wrote:
A tuple is basically an anonymous product type. It's convenient to not
have to spend the time making a named product type, because product types are so obviously useful.
Is there any reason why Haskell doesn't have anonymous sum types? If there isn't some theoretical problem, is there any practical reason why they haven't been implemented?
The Either type is the nearest Haskell comes to having anonymous sum types.
If you are bothered because Either has a name and constructors, it does not take long before you realise that (,) has a name and a constructor too.
Yes, Either is to sum types what (,) is to product types. The difference is that there is no "anonymous" sum type equivalent to (,,) and (,,,) and (,,,,) and so on, which I think is what the original question is getting at. Indeed, I sometimes wish I could write something like (straw-man syntax):
foo :: (Int | Bool | String | Double) -> Int foo x = case x of 1stOf4 i -> i + 7 2ndOf4 b -> if b then 1 else 0 3rdOf4 s -> length s 4thOf4 d -> floor d bar :: Int bar = foo (2ndOf4 True)
and have that work for any size of sum type. But I can't.
The syntax is truly awful, but this doesn't seem that far from foo :: Either Int (Either Bool (Either String Double)) -> Int foo (Left e) = e + 7 foo (Right (Left e )) = if e then 1 else 0 foo (Right (Right (Left e))) = length e foo (Right (Right (Right e))) = floor e foo . Right . Left $ True Mike

On Tue, Jun 21, 2011 at 3:36 PM, Matthew Steele
On Jun 21, 2011, at 4:02 PM, Malcolm Wallace wrote:
On 21 Jun 2011, at 20:53, Elliot Stern wrote:
A tuple is basically an anonymous product type. It's convenient to not have to spend the time making a named product type, because product types are so obviously useful.
Is there any reason why Haskell doesn't have anonymous sum types? If there isn't some theoretical problem, is there any practical reason why they haven't been implemented?
The Either type is the nearest Haskell comes to having anonymous sum types.
If you are bothered because Either has a name and constructors, it does not take long before you realise that (,) has a name and a constructor too.
Yes, Either is to sum types what (,) is to product types. The difference is that there is no "anonymous" sum type equivalent to (,,) and (,,,) and (,,,,) and so on, which I think is what the original question is getting at. Indeed, I sometimes wish I could write something like (straw-man syntax):
foo :: (Int | Bool | String | Double) -> Int foo x = case x of 1stOf4 i -> i + 7 2ndOf4 b -> if b then 1 else 0 3rdOf4 s -> length s 4thOf4 d -> floor d bar :: Int bar = foo (2ndOf4 True)
and have that work for any size of sum type. But I can't.
Why not just do what we do for tuples? Define a bunch of generic types up front: data Choice2 a b = OneOf2 a | TwoOf2 b data Choice3 a b c = OneOf3 a | TwoOf3 b | ThreeOf3 c . . . Then you wouldn't need any special compiler support, and you can release it on its own library on Hackage. I don't think I would use it, be to each their own!
Cheers, -Matt
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Why not just do what we do for tuples? Define a bunch of generic types up front: data Choice2 a b = OneOf2 a | TwoOf2 b data Choice3 a b c = OneOf3 a | TwoOf3 b | ThreeOf3 c The module Text.XML.HaXml.OneOfN defines these types up to size 20. The package HaXml also comes with a small command-line driven generator tool (called MkOneOf) that can automatically write you a OneOfN type (or set of types) of arbitrary finite size. (Being part of HaXml, it also generates instances of some XML reading/writing classes as well.) Regards, Malcolm

On Tue, Jun 21, 2011 at 1:36 PM, Matthew Steele
Yes, Either is to sum types what (,) is to product types. The difference is that there is no "anonymous" sum type equivalent to (,,) and (,,,) and (,,,,) and so on, which I think is what the original question is getting at. Indeed, I sometimes wish I could write something like (straw-man syntax):
foo :: (Int | Bool | String | Double) -> Int foo x = case x of 1stOf4 i -> i + 7 2ndOf4 b -> if b then 1 else 0 3rdOf4 s -> length s 4thOf4 d -> floor d bar :: Int bar = foo (2ndOf4 True)
and have that work for any size of sum type. But I can't.
Haskell operators are pretty flexible. You can get something really close without much effort. Consider: import Data.Either type (:|:) a b = Either a b (???) = either foo :: (Int :|: Bool :|: String :|: Double) -> Int foo = \ i -> i + 7 ??? \ b -> if b then 1 else 0 ??? \ s -> length s ??? \ d -> floor d

import Data.Either type (:|:) a b = Either a b (???) = either
foo :: (Int :|: Bool :|: String :|: Double) -> Int foo = \ i -> i + 7 ??? \ b -> if b then 1 else 0 ??? \ s -> length s ??? \ d -> floor d
INFIX TYPE OPERATORS!!??! O_________________________________________O

Arlen Cuss
import Data.Either type (:|:) a b = Either a b (???) = either
foo :: (Int :|: Bool :|: String :|: Double) -> Int foo = \ i -> i + 7 ??? \ b -> if b then 1 else 0 ??? \ s -> length s ??? \ d -> floor d
INFIX TYPE OPERATORS!!??!
O_________________________________________O
Yep. http://www.haskell.org/ghc/docs/7.0.3/html/users_guide/data-type-extensions.... -- lelf

On Tue, Jun 21, 2011 at 12:53 PM, Elliot Stern
A tuple is basically an anonymous product type. It's convenient to not have to spend the time making a named product type, because product types are so obviously useful.
Tuples are not so anonymous. Although syntactic sugar complicates the issue, there is basically a data constructor named (,).
Is there any reason why Haskell doesn't have anonymous sum types? If there isn't some theoretical problem, is there any practical reason why they haven't been implemented?
The problem is that a sum type must "name" the different types, or else it can't give access to them. How is a function supposed to know if a value blah :: A :+: B is an A or a B? It seems possible that it could figure it out, but that problem is undecidable in general.

On Jun 21, 4:15 pm, Alexander Solla
The problem is that a sum type must "name" the different types, or else it can't give access to them. How is a function supposed to know if a value
blah :: A :+: B
is an A or a B? It seems possible that it could figure it out, but that problem is undecidable in general.
Why can't you use pattern matching? We'd probably want to change the syntax a little, to tell Haskell that we want to use an anonymous sum. Something like: foo :: Bar :+: Baz -> Quux foo <Bar bar> = ... foo <Baz baz> = ... Would finding the type signature of foo be undecidable?

On 22.06.2011 00:32, pipoca wrote:
On Jun 21, 4:15 pm, Alexander Solla
wrote: The problem is that a sum type must "name" the different types, or else it can't give access to them. How is a function supposed to know if a value
blah :: A :+: B
is an A or a B? It seems possible that it could figure it out, but that problem is undecidable in general.
Why can't you use pattern matching? We'd probably want to change the syntax a little, to tell Haskell that we want to use an anonymous sum.
Something like:
foo :: Bar :+: Baz -> Quux foo<Bar bar> = ... foo<Baz baz> = ...
Would finding the type signature of foo be undecidable?
Types may be same. oops :: Int :+: Int -> Int oops <Int i> = mmm which one?

On Jun 21, 4:57 pm, Alexey Khudyakov
Types may be same.
oops :: Int :+: Int -> Int oops <Int i> = mmm which one?
If you were to have your anonymous sum types be a union instead of the disjoint union, then you could say that A :+: A has no meaning. That's what I was originally thinking of when I suggested that syntax. However, as was pointed out to me by David Sankel, disjoint unions are more powerful than regular unions. Since that's the case, Matthew Steele's suggested syntax makes more sense. It means that you need to remember the order of your arguments, but you need to do that with tuples, anyway.

On Tue, Jun 21, 2011 at 5:24 PM, pipoca
If you were to have your anonymous sum types be a union instead of the disjoint union, then you could say that A :+: A has no meaning. That's what I was originally thinking of when I suggested that syntax. However, as was pointed out to me by David Sankel, disjoint unions are more powerful than regular unions. Since that's the case, Matthew Steele's suggested syntax makes more sense. It means that you need to remember the order of your arguments, but you need to do that with tuples, anyway.
Of course, the same idea could be applied to tuples as well. An "anonymous product" A :*: B would be a collection with no defined order for its elements, indexed by type instead of position. A :*: A would be meaningless for similar reasons to A :+: A. That said, I don't think either retains the tidy algebraic properties that disjoint unions and tuples have, so I'm not sure if calling them sums and products is actually correct. - C.

On Tue, Jun 21, 2011 at 2:24 PM, pipoca
On Jun 21, 4:57 pm, Alexey Khudyakov
wrote: Types may be same.
oops :: Int :+: Int -> Int oops <Int i> = mmm which one?
If you were to have your anonymous sum types be a union instead of the disjoint union, then you could say that A :+: A has no meaning.
That sort of union would not be parametric, and would play havoc with generic programming. E.g. consider taking a list [(t,Int)] and [(t,a)] and generating a list of [(t,Int :+: a)], then processing this with a function of the form Int -> Bool.
participants (13)
-
Alexander Solla
-
Alexey Khudyakov
-
Antoine Latter
-
Anton Nikishaev
-
Arlen Cuss
-
Casey McCann
-
David Barbour
-
Elliot Stern
-
Malcolm Wallace
-
malcolm.wallace
-
Matthew Steele
-
Mike Erickson
-
pipoca