[lib] Can we add an enum `Either` in std?

Sometime, I need to write a very simple enum type. Result type in std is not suitable for some cases, because the two variants in Result type suggest very different intentions.

I would very happy to see a generic Either type in std:

enum Either<T1, T2> {
  Left(T1),
  Right(T2),
}

If we can leverage variadic generics, it can be designed even better.

We could think of it as counterpart of tuple for convenience, one is for product type and the other is for sum type.

Is this type qualified to be added into std?

4 Likes

I expect the Rust idiom would be to create a more specific enum in most cases. Can you describe a use case for generic Either?

7 Likes

We used to have Either, but nobody used it, so we removed it.

https://crates.io/crates/either

will give you the above if you need it.

7 Likes

Thanks for your explanation.

As of now the official stance is that folks should define their own two-variant enums with domain-specific names. I have to admit that I sometimes want it though. The external crate is still probably the way to go though - slightly discourages its use but it’s still available.

2 Likes

In crate either, a trait problem is already apparent. It has some trait impls that make it easy to use for some drop-in use cases, and those block other reasonable choices for trait impls.

Specifically it covers I need a general “either this iterator or the other iterator enum” using an Iterator impl. That choice excludes Either from implementing IntoIterator instead.

The either crate may be a good choice if one needs it for a function argument and can’t name the situation more specifically.

3 Likes

I’m just trying something in haskell (rust as a gateway drug…) and found myself reaching for the ‘Either’ ;

I was also therefore curious to know if Rust had one;

r.e. making something domain specific with names, the appeal of Either here is that you’re already specifying two types (i.e. giving distinct names) (Either<FOO,BAR> … this node is either an FOO or a BAR’) , in some contexts those may be sufficient explain what is going on. tangentially, Imagine if the language actually had a ‘types not equal’ constraint (e.g. where A!=B) , which would enforce the ability to select by type (e.g. also imagine tuple accessors .get<A>(), .get<B>()) or .is<A>() .is<B>() for ‘either’ . https://github.com/rust-lang/rust/issues/42861 and imagine generalizing ‘a generic enum of 3 things’, etc.

I note that in haskell they do also fill out a load of helper functions around this. https://hackage.haskell.org/package/base-4.9.1.0/docs/Data-Either.html Also maybe there’d be utility in a ‘SoaVec<A,B> aswell’ with similar by-type accessor (although I guess macros could do that better for SOA stuff)

1 Like

Nothing has changed since my post on March 17.

1 Like

We already have Either in futures crate. It’s also is confusing because it looks just like Either from either crate when it’s not.

Because Futures seems to be merged in std (at least very basic parts of it) could we also include Either there? It’s crucial to have them in order to be able to return impl Future from the function.

1 Like

Note that futures(0.2) and futures(0.3-alpha) re-use either::Either instead of defining their own. Although, futures(0.3) can’t have impl Future for Either because of coherence, only Stream and Sink. So it’s likely going to drop that support and instead provide it’s own set of n-ary sum types.

1 Like

I believe the state of art in n-ary coproduct (sum-type) hackery is provided by the frunk crate… it is probably way too much; but have a look at it :slight_smile:

1 Like

I’ll just leave this here again: https://github.com/rust-lang/rfcs/pull/1154

4 Likes

I’m hoping we’ll eventually get either auto-generated delegating sum types, or variadic implementations on anonymous sum types. I’m gonna have to take another look at frunk to see if there’s some way to sort of emulate the second.

2 Likes

Either would be nice for things like splitting an iterator.

e.g.

let x: (Vec<_>, Vec) = iter.collect_split(|e| Left(e));

1 Like

That's Itertools::partition_map.

1 Like

If such a thing does go in std (and I’m not saying it should), can I make a small plea?

Don’t call the variants Left and Right, please pick names that are the same length so match blocks line up :). This annoys me every time I see it.

4 Likes

One/Two is not original enough I guess?

1 Like

This/That

2 Likes

We used to have Either, but it was never used, so t was removed.

There’s a crate on crates.io for it.

1 Like

I think that was because we don’t have impl Trait at the moment. Bur now when we have it, it becomes essential to return different concrete types in different branches.

2 Likes