#[derive(Debug)]
pub enum Either<A, B> {
    A(A),
    B(B),
}

impl<A, B> Either<A, B> {
    // pub fn map_a<C>(self, f: impl FnOnce(A) -> C) -> Either<C, B> {
    //     match self {
    //         Either::A(a) => Either::A(f(a)),
    //         Either::B(b) => Either::B(b),
    //     }
    // }
    pub fn map_b<C>(self, f: impl FnOnce(B) -> C) -> Either<A, C> {
        match self {
            Either::A(a) => Either::A(a),
            Either::B(b) => Either::B(f(b)),
        }
    }

    pub fn get_a(&self) -> Option<&A> {
        match self {
            Either::A(a) => Some(a),
            Either::B(_) => None,
        }
    }

    pub fn get_b(&self) -> Option<&B> {
        match self {
            Either::A(_) => None,
            Either::B(b) => Some(b),
        }
    }
}

impl<A, B, E> Either<A, Result<B, E>> {
    pub fn transpose_b(self) -> Result<Either<A, B>, E> {
        match self {
            Either::A(a) => Ok(Either::A(a)),
            Either::B(Ok(b)) => Ok(Either::B(b)),
            Either::B(Err(e)) => Err(e),
        }
    }
}
