Description
There is an into_inner()
method on Either<T, T>
that can "unwrap" the inner value as long as both arms have the same type.
This is useful, but a more generic conversion could be implemented for any Either<A, B>
to any type T
that implements From<A> + From<B>
.
Such a trait would be simple to blanket implement:
pub trait FromEither<A, B> {
fn from_either(either: Either<A, B>) -> Self;
}
impl<A, B, T> FromEither<A, B> for T
where
T: From<A> + From<B>,
{
fn from_either(either: Either<A, B>) -> Self {
match either {
Left(a) => Self::from(a),
Right(b) => Self::from(b),
}
}
}
Programmers would rarely implement this directly, but rely on the blanket implementation to kick in when they've implemented From
for each arm of an Either
on their type.
Why would this be useful? Consider an Iterator
of Either
values. One may with to transform those values into another enum:
#[derive(Debug)]
struct A;
#[derive(Debug)]
struct B;
#[derive(Debug)]
enum C {
A(A),
B(B),
}
impl From<A> for C {
fn from(a: A) -> Self {
C::A(a)
}
}
impl From<B> for C {
fn from(b: B) -> Self {
C::B(b)
}
}
fn main() {
[Left(A), Right(B), Left(A), Right(B)]
.into_iter()
.map(C::from_either)
.for_each(|c| {
println!("{c:?}");
});
}
If the arms are the same, we could use Either::into_inner
as the function passed to map()
. FromEither
is useful specifically if the arms are different but still convertible to a common type.
My current workaround is to use map(|ab| ab.either(C::from, C::from))
in situations like this, which works, but is a little more verbose than map(C::from_either)
.