import Base import ./lib.bend as DQ # empty is D{Nil, Nil}. law empty_is_d_nil: for -a: Quant for -A: Kind(a) { DQ.Deque.empty(a, A) == DQ.D{Nil{}, Nil{}} : DQ.Deque } # Empty has no front element. law peek_front_empty: for -a: Quant for -A: Kind(a) { DQ.Deque.peek_front(a, A, DQ.Deque.empty(a, A)) == None{} : Maybe } # Empty has no back element. law peek_back_empty: for -a: Quant for -A: Kind(a) { DQ.Deque.peek_back(a, A, DQ.Deque.empty(a, A)) == None{} : Maybe } # Empty pops from either end to None. law pop_front_empty: for -a: Quant for -A: Kind(a) { DQ.Deque.pop_front(a, A, DQ.Deque.empty(a, A)) == None{} : Maybe> } law pop_back_empty: for -a: Quant for -A: Kind(a) { DQ.Deque.pop_back(a, A, DQ.Deque.empty(a, A)) == None{} : Maybe> } law to_list_empty: for -a: Quant for -A: Kind(a) { DQ.Deque.to_list(a, A, DQ.Deque.empty(a, A)) == Nil{} : List } law length_empty: for -a: Quant for -A: Kind(a) { DQ.Deque.length(a, A, DQ.Deque.empty(a, A)) == 0n : Nat } law is_empty_empty: for -a: Quant for -A: Kind(a) { DQ.Deque.is_empty(a, A, DQ.Deque.empty(a, A)) == True{} : Bool } # Definitional characterization of the two-list order. law to_list_d: for -a: Quant for -A: Kind(a) for f: List for r: List { DQ.Deque.to_list(a, A, DQ.D{f, r}) == List.append(a, A, f, List.reverse(a, A, r)) : List } law length_d: for -a: Quant for -A: Kind(a) for f: List for r: List { DQ.Deque.length(a, A, DQ.D{f, r}) == Nat.add(List.length(a, A, f), List.length(a, A, r)) : Nat } law from_list_d: for -a: Quant for -A: Kind(a) for xs: List { DQ.Deque.from_list(a, A, xs) == DQ.D{xs, Nil{}} : DQ.Deque } law from_list_empty: for -a: Quant for -A: Kind(a) { DQ.Deque.from_list(a, A, Nil{}) == DQ.Deque.empty(a, A) : DQ.Deque } law from_list_singleton_roundtrip: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.to_list(a, A, DQ.Deque.from_list(a, A, x <> Nil{})) == x <> Nil{} : List } law push_front_d: for -a: Quant for -A: Kind(a) for f: List for r: List for x: A { DQ.Deque.push_front(a, A, DQ.D{f, r}, x) == DQ.D{x <> f, r} : DQ.Deque } law push_back_d: for -a: Quant for -A: Kind(a) for f: List for r: List for x: A { DQ.Deque.push_back(a, A, DQ.D{f, r}, x) == DQ.D{f, x <> r} : DQ.Deque } # Pushing at either end produces the same singleton order. law push_front_singleton: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.to_list(a, A, DQ.Deque.push_front(a, A, DQ.Deque.empty(a, A), x)) == x <> Nil{} : List } law push_back_singleton: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.to_list(a, A, DQ.Deque.push_back(a, A, DQ.Deque.empty(a, A), x)) == x <> Nil{} : List } law length_push_front_empty: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.length(a, A, DQ.Deque.push_front(a, A, DQ.Deque.empty(a, A), x)) == 1n : Nat } law length_push_back_empty: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.length(a, A, DQ.Deque.push_back(a, A, DQ.Deque.empty(a, A), x)) == 1n : Nat } law is_empty_push_front: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.is_empty(a, A, DQ.Deque.push_front(a, A, DQ.Deque.empty(a, A), x)) == False{} : Bool } law is_empty_push_back: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.is_empty(a, A, DQ.Deque.push_back(a, A, DQ.Deque.empty(a, A), x)) == False{} : Bool } law peek_front_push_front: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.peek_front(a, A, DQ.Deque.push_front(a, A, DQ.Deque.empty(a, A), x)) == Some{x} : Maybe } law peek_back_push_back: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.peek_back(a, A, DQ.Deque.push_back(a, A, DQ.Deque.empty(a, A), x)) == Some{x} : Maybe } law peek_front_push_back: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.peek_front(a, A, DQ.Deque.push_back(a, A, DQ.Deque.empty(a, A), x)) == Some{x} : Maybe } law peek_back_push_front: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.peek_back(a, A, DQ.Deque.push_front(a, A, DQ.Deque.empty(a, A), x)) == Some{x} : Maybe } # Singleton pops recover the value and an empty deque. law pop_front_push_front_empty: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.pop_front(a, A, DQ.Deque.push_front(a, A, DQ.Deque.empty(a, A), x)) == Some{DQ.P{x, DQ.Deque.empty(a, A)}} : Maybe> } law pop_front_push_back_empty: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.pop_front(a, A, DQ.Deque.push_back(a, A, DQ.Deque.empty(a, A), x)) == Some{DQ.P{x, DQ.Deque.empty(a, A)}} : Maybe> } law pop_back_push_back_empty: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.pop_back(a, A, DQ.Deque.push_back(a, A, DQ.Deque.empty(a, A), x)) == Some{DQ.P{x, DQ.Deque.empty(a, A)}} : Maybe> } law pop_back_push_front_empty: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.pop_back(a, A, DQ.Deque.push_front(a, A, DQ.Deque.empty(a, A), x)) == Some{DQ.P{x, DQ.Deque.empty(a, A)}} : Maybe> } law pop_front_cons: for -a: Quant for -A: Kind(a) for h: A for t: List for r: List { DQ.Deque.pop_front(a, A, DQ.D{h <> t, r}) == Some{DQ.P{h, DQ.D{t, r}}} : Maybe> } law pop_back_cons: for -a: Quant for -A: Kind(a) for f: List for h: A for t: List { DQ.Deque.pop_back(a, A, DQ.D{f, h <> t}) == Some{DQ.P{h, DQ.D{f, t}}} : Maybe> } law norm_front_cons: for -a: Quant for -A: Kind(a) for h: A for t: List for r: List { DQ.Deque.norm_front(a, A, DQ.D{h <> t, r}) == DQ.D{h <> t, r} : DQ.Deque } law norm_back_cons: for -a: Quant for -A: Kind(a) for f: List for h: A for t: List { DQ.Deque.norm_back(a, A, DQ.D{f, h <> t}) == DQ.D{f, h <> t} : DQ.Deque } law norm_front_rear_one: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.norm_front(a, A, DQ.D{Nil{}, x <> Nil{}}) == DQ.D{x <> Nil{}, Nil{}} : DQ.Deque } law norm_back_front_one: for -a: Quant for -A: Kind(a) for x: A { DQ.Deque.norm_back(a, A, DQ.D{x <> Nil{}, Nil{}}) == DQ.D{Nil{}, x <> Nil{}} : DQ.Deque } # push_front then push_back order. law to_list_front_then_back: for -a: Quant for -A: Kind(a) for x: A for y: A { DQ.Deque.to_list(a, A, DQ.Deque.push_back(a, A, DQ.Deque.push_front(a, A, DQ.Deque.empty(a, A), x), y)) == x <> (y <> Nil{}) : List }