use crate::{ops::{Add, Sub}, term::{Term, ValueEq}, type_eq::refl};
use super::{add::{a_plus_0_eq_a, a_plus_s_b_eq_s_add_a_b, add_0_a_eq_a, add_associative, add_commutative, add_eq_to_left_eq, s_a_plus_b_eq_s_add_a_b}, succ_eq_to_eq, Int, Succ, Zero};
pub fn a_minus_b_plus_b_eq_a<N, A: Term<Type = N>, B: Term<Type = N>>(
) -> ValueEq<Add<Sub<A, B>, B>, A>
where N: Int
{
unsafe {ValueEq::axiom()}
}
pub fn add_sub_associative<N, A: Term<Type = N>, B: Term<Type = N>, C: Term<Type = N>>(
) -> ValueEq<Add<A, Sub<B, C>>, Sub<Add<A, B>, C>>
where N: Int
{
let lemma = -add_associative() + Add::eq(refl(), a_minus_b_plus_b_eq_a()) - a_minus_b_plus_b_eq_a();
add_eq_to_left_eq(lemma, refl())
}
#[allow(non_snake_case)]
pub fn a_plus_b_minus_b_eq_a<N, A: Term<Type = N>, B: Term<Type = N>>(
) -> ValueEq<Sub<Add<A, B>, B>, A>
where N: Int
{
add_eq_to_left_eq(a_minus_b_plus_b_eq_a(), refl())
}
pub fn sub_add_associative<N, A: Term<Type = N>, B: Term<Type = N>, C: Term<Type = N>>(
) -> ValueEq<Sub<A, Add<B, C>>, Sub<Sub<A, B>, C>>
where N: Int
{
let lemma = a_minus_b_plus_b_eq_a() - a_minus_b_plus_b_eq_a() + Add::eq(-a_minus_b_plus_b_eq_a(), refl()) - add_associative() + Add::eq(refl(), add_commutative());
add_eq_to_left_eq(lemma, refl())
}
pub fn add_sub_commutative<N, A: Term<Type = N>, B: Term<Type = N>, C: Term<Type = N>>(
) -> ValueEq<Add<Sub<A, B>, C>, Sub<Add<A, C>, B>>
where N: Int
{
let lemma = -add_associative() + Add::eq(refl(), add_commutative()) + add_associative() + Add::eq(a_minus_b_plus_b_eq_a(), refl()) - a_minus_b_plus_b_eq_a();
add_eq_to_left_eq(lemma, refl())
}
pub fn a_minus_sub_b_c_eq_a_plus_sub_c_b<N, A: Term<Type = N>, B: Term<Type = N>, C: Term<Type = N>>(
) -> ValueEq<Sub<A, Sub<B, C>>, Add<A, Sub<C, B>>>
where N: Int
{
let lemma = add_associative() + Add::eq(a_minus_b_plus_b_eq_a(), refl()) + Add::eq(refl(), -a_minus_b_plus_b_eq_a()) + add_associative() + Add::eq(refl(), -a_minus_b_plus_b_eq_a());
add_eq_to_left_eq(lemma, refl())
}
pub fn sub_sub_associative<N, A: Term<Type = N>, B: Term<Type = N>, C: Term<Type = N>>(
) -> ValueEq<Sub<A, Sub<B, C>>, Add<Sub<A, B>, C>>
where N: Int
{
a_minus_sub_b_c_eq_a_plus_sub_c_b() + add_sub_associative() - add_sub_commutative()
}
pub fn a_minus_a_eq_0<N, A: Term<Type = N>>(
) -> ValueEq<Sub<A, A>, Zero<N>>
where N: Int
{
let lemma = a_minus_b_plus_b_eq_a() - a_plus_0_eq_a() + add_commutative();
add_eq_to_left_eq(lemma, refl())
}
pub fn a_minus_0_eq_a<N, A: Term<Type = N>>(
) -> ValueEq<Sub<A, Zero<N>>, A>
where N: Int
{
let lemma = a_minus_b_plus_b_eq_a() - a_plus_0_eq_a();
add_eq_to_left_eq(lemma, refl())
}
pub fn s_a_minus_s_b_eq_a_minus_b<N, A: Term<Type = N>, B: Term<Type = N>>(
) -> ValueEq<Sub<Succ<A>, Succ<B>>, Sub<A, B>>
where N: Int
{
let lemma = succ_eq_to_eq(-a_plus_s_b_eq_s_add_a_b() + a_minus_b_plus_b_eq_a());
-a_plus_b_minus_b_eq_a() + Sub::eq(lemma, refl())
}
#[allow(non_snake_case)]
pub fn s_a_minus_b_eq_s_sub_a_b<N, A: Term<Type = N>, B: Term<Type = N>>(
) -> ValueEq<Sub<Succ<A>, B>, Succ<Sub<A, B>>>
where N: Int
{
let lemma = s_a_plus_b_eq_s_add_a_b() + Succ::eq(a_minus_b_plus_b_eq_a());
-Sub::eq(lemma, refl()) + a_plus_b_minus_b_eq_a()
}
pub fn s_a_minus_s_0_eq_a<N, A: Term<Type = N>>(
) -> ValueEq<Sub<Succ<A>, Succ<Zero<N>>>, A>
where N: Int
{
s_a_minus_s_b_eq_a_minus_b() + a_minus_0_eq_a()
}
pub fn s_sub_a_s_b_eq_a_minus_b<N, A: Term<Type = N>, B: Term<Type = N>>(
) -> ValueEq<Succ<Sub<A, Succ<B>>>, Sub<A, B>>
where N: Int
{
-s_a_minus_b_eq_s_sub_a_b() + s_a_minus_s_b_eq_a_minus_b()
}
pub fn s_sub_a_s_0_eq_a<N, A: Term<Type = N>>(
) -> ValueEq<Succ<Sub<A, Succ<Zero<N>>>>, A>
where N: Int
{
s_sub_a_s_b_eq_a_minus_b() + a_minus_0_eq_a()
}
pub fn sub_eq_to_left_eq<N, A: Term<Type = N>, B: Term<Type = N>, C: Term<Type = N>, D: Term<Type = N>>(
eq: ValueEq<Sub<A, C>, Sub<B, D>>,
c_eq_d: ValueEq<C, D>
) -> ValueEq<A, B>
where N: Int
{
-a_minus_b_plus_b_eq_a() + Add::eq(eq, c_eq_d) + a_minus_b_plus_b_eq_a()
}
pub fn a_minus_sub_a_b_eq_b<N, A: Term<Type = N>, B: Term<Type = N>>(
) -> ValueEq<Sub<A, Sub<A, B>>, B>
where N: Int
{
sub_sub_associative() + Add::eq(a_minus_a_eq_0(), refl()) + add_0_a_eq_a()
}
pub fn sub_eq_to_right_eq<N, A: Term<Type = N>, B: Term<Type = N>, C: Term<Type = N>, D: Term<Type = N>>(
eq: ValueEq<Sub<A, C>, Sub<B, D>>,
a_eq_b: ValueEq<A, B>
) -> ValueEq<C, D>
where N: Int
{
-a_minus_sub_a_b_eq_b() + Sub::eq(a_eq_b, eq) + a_minus_sub_a_b_eq_b()
}