use crate::arrow::Arrow;
pub trait ArrowChoice: Arrow {
fn left<A: Clone + 'static, B: Clone + 'static, C: Clone + 'static>(
pab: Self::P<A, B>,
) -> Self::P<Result<A, C>, Result<B, C>>;
fn right<A: Clone + 'static, B: Clone + 'static, C: Clone + 'static>(
pab: Self::P<A, B>,
) -> Self::P<Result<C, A>, Result<C, B>> {
let mirror_in = Self::arr(|r: Result<C, A>| match r {
Ok(c) => Err(c),
Err(a) => Ok(a),
});
let mirror_out = Self::arr(|r: Result<B, C>| match r {
Ok(b) => Err(b),
Err(c) => Ok(c),
});
Self::compose(mirror_out, Self::compose(Self::left(pab), mirror_in))
}
fn splat<A: Clone + 'static, B: Clone + 'static, C: Clone + 'static, D: Clone + 'static>(
f: Self::P<A, B>,
g: Self::P<C, D>,
) -> Self::P<Result<A, C>, Result<B, D>> {
Self::compose(Self::right(g), Self::left(f))
}
fn fanin<A: Clone + 'static, B: Clone + 'static, C: Clone + 'static>(
f: Self::P<A, C>,
g: Self::P<B, C>,
) -> Self::P<Result<A, B>, C> {
let merge = Self::arr(|r: Result<C, C>| match r {
Ok(c) | Err(c) => c,
});
Self::compose(merge, Self::splat(f, g))
}
}