# int.bend -- the integers, as a bounty: a canonical # representation is FIXED here (so that == is real equality), the # operations are open (laws with no def), and the laws and test cases # are open claims about them. Fill the operations first, in a new file # that imports this one with an alias; every test case is then {==}. # # Int.Pos{n} is n, Int.NegS{n} is -(1+n). Nothing else represents an # integer, so there is exactly one term per integer. import Base import ./nat.bend as N type Int is Data: Pos{n: Nat} NegS{n: Nat} def Int.of(n: Nat) -> Int: Pos{n} def Int.zero() -> Int: Pos{0n} def Int.one() -> Int: Pos{1n} # ---- operations (open) -------------------------------------------------- law Int.neg: for a: Int Int law Int.add: for a: Int for b: Int Int law Int.mul: for a: Int for b: Int Int law Int.sub: for a: Int for b: Int Int # the absolute value, as a Nat law Int.abs: for a: Int Nat # a <= b as a computed proposition (Unit or Empty), like N.Nat.Le law Int.Le: for a: Int for b: Int Type # ---- test cases (each is {==} once the operations compute) ------------- law t_add_1: {Int.add(Pos{3n}, NegS{4n}) == NegS{1n} : Int} law t_add_2: {Int.add(NegS{0n}, Pos{1n}) == Pos{0n} : Int} law t_mul_1: {Int.mul(NegS{1n}, NegS{2n}) == Pos{6n} : Int} law t_mul_2: {Int.mul(Pos{3n}, NegS{0n}) == NegS{2n} : Int} law t_sub_1: {Int.sub(Pos{0n}, Pos{5n}) == NegS{4n} : Int} law t_abs_1: {Int.abs(NegS{6n}) == 7n : Nat} # ---- laws (open) -------------------------------------------------------- # 1. Int.of embeds Nat: addition and multiplication agree with Nat's law of_add: for +a: Nat for +b: Nat {Int.add(Pos{a}, Pos{b}) == Pos{Nat.add(a, b)} : Int} law of_mul: for +a: Nat for +b: Nat {Int.mul(Pos{a}, Pos{b}) == Pos{Nat.mul(a, b)} : Int} # 2. sub is add of the negation law sub_def: for +a: Int for +b: Int {Int.sub(a, b) == Int.add(a, Int.neg(b)) : Int} # 3. a + (-a) = 0, and -(-a) = a law add_neg: for +a: Int {Int.add(a, Int.neg(a)) == Pos{0n} : Int} law neg_neg: for a: Int {Int.neg(Int.neg(a)) == a : Int} # 4. (Int, add, 0) is a commutative group; (Int, mul, 1) a commutative # monoid; mul distributes over add law add_zero: for a: Int {Int.add(a, Pos{0n}) == a : Int} law add_comm: for +a: Int for +b: Int {Int.add(a, b) == Int.add(b, a) : Int} law add_assoc: for +a: Int for +b: Int for +c: Int {Int.add(a, Int.add(b, c)) == Int.add(Int.add(a, b), c) : Int} law mul_one: for a: Int {Int.mul(a, Pos{1n}) == a : Int} law mul_zero: for a: Int {Int.mul(a, Pos{0n}) == Pos{0n} : Int} law mul_comm: for +a: Int for +b: Int {Int.mul(a, b) == Int.mul(b, a) : Int} law mul_assoc: for +a: Int for +b: Int for +c: Int {Int.mul(a, Int.mul(b, c)) == Int.mul(Int.mul(a, b), c) : Int} law mul_add: for +a: Int for +b: Int for +c: Int {Int.mul(a, Int.add(b, c)) == Int.add(Int.mul(a, b), Int.mul(a, c)) : Int} # 5. no zero divisors (what the rationals will need) law mul_eq_zero: for +a: Int for +b: Int for e: {Int.mul(a, b) == Pos{0n} : Int} for na: {a == Pos{0n} : Int} -> Empty {b == Pos{0n} : Int} # 6. the order: total, antisymmetric, compatible with add and with mul by # a non-negative law le_refl: for a: Int Int.Le(a, a) law le_antisym: for +a: Int for +b: Int for h1: Int.Le(a, b) for h2: Int.Le(b, a) {a == b : Int} law le_trans: for +a: Int for +b: Int for +c: Int for h1: Int.Le(a, b) for h2: Int.Le(b, c) Int.Le(a, c) law le_add: for +a: Int for +b: Int for +c: Int for h: Int.Le(a, b) Int.Le(Int.add(a, c), Int.add(b, c)) law le_mul_nonneg: for +a: Int for +b: Int for +n: Nat for h: Int.Le(a, b) Int.Le(Int.mul(a, Pos{n}), Int.mul(b, Pos{n})) # 7. neg reverses the order, and Pos{n} is never negative law le_neg: for +a: Int for +b: Int for h: Int.Le(a, b) Int.Le(Int.neg(b), Int.neg(a)) law pos_nonneg: for n: Nat Int.Le(Pos{0n}, Pos{n})