import Base
import ./lib.bend as Q
# to_list(empty) is Nil.
law to_list_empty:
for -a: Quant
for -A: Kind(a)
{ Q.Queue.to_list(a, A, Q.Queue.empty(a, A)) == Nil{} : List }
# empty is Q{Nil, Nil}.
law empty_is_q_nil:
for -a: Quant
for -A: Kind(a)
{ Q.Queue.empty(a, A) == Q.Q{Nil{}, Nil{}} : Q.Queue }
# to_list unfolds to front ++ reverse(rear).
law to_list_q:
for -a: Quant
for -A: Kind(a)
for f: List
for r: List
{ Q.Queue.to_list(a, A, Q.Q{f, r}) == List.append(a, A, f, List.reverse(a, A, r)) : List }
# Enqueue on empty yields a singleton list in FIFO order.
law to_list_enqueue_empty:
for -a: Quant
for -A: Kind(a)
for x: A
{ Q.Queue.to_list(a, A, Q.Queue.enqueue(a, A, Q.Queue.empty(a, A), x)) == x <> Nil{} : List }
# enqueue(empty, x) puts x on the rear.
law enqueue_empty:
for -a: Quant
for -A: Kind(a)
for x: A
{ Q.Queue.enqueue(a, A, Q.Queue.empty(a, A), x) == Q.Q{Nil{}, x <> Nil{}} : Q.Queue }
# enqueue preserves front and conses onto rear.
law enqueue_q:
for -a: Quant
for -A: Kind(a)
for f: List
for r: List
for x: A
{ Q.Queue.enqueue(a, A, Q.Q{f, r}, x) == Q.Q{f, x <> r} : Q.Queue }
# dequeue(enqueue(empty, x)) recovers x and an empty rest.
law dequeue_enqueue_empty:
for -a: Quant
for -A: Kind(a)
for x: A
{
Q.Queue.dequeue(a, A, Q.Queue.enqueue(a, A, Q.Queue.empty(a, A), x))
== Some{Q.HD{x, Q.Queue.empty(a, A)}}
: Maybe>
}
# dequeue with nonempty front recovers head without rotating.
law dequeue_front_cons:
for -a: Quant
for -A: Kind(a)
for h: A
for t: List
for r: List
{
Q.Queue.dequeue(a, A, Q.Q{h <> t, r})
== Some{Q.HD{h, Q.Q{t, r}}}
: Maybe>
}
# dequeue(from_list(h <> t)) recovers h.
law dequeue_from_cons:
for -a: Quant
for -A: Kind(a)
for h: A
for t: List
{
Q.Queue.dequeue(a, A, Q.Queue.from_list(a, A, h <> t))
== Some{Q.HD{h, Q.Q{t, Nil{}}}}
: Maybe>
}
# peek(empty) is None.
law peek_empty:
for -a: Quant
for -A: Kind(a)
{ Q.Queue.peek(a, A, Q.Queue.empty(a, A)) == None{} : Maybe }
# peek(enqueue(empty, x)) recovers x.
law peek_enqueue_empty:
for -a: Quant
for -A: Kind(a)
for x: A
{ Q.Queue.peek(a, A, Q.Queue.enqueue(a, A, Q.Queue.empty(a, A), x)) == Some{x} : Maybe }
# peek(from_list(h <> t)) recovers h.
law peek_from_cons:
for -a: Quant
for -A: Kind(a)
for h: A
for t: List
{ Q.Queue.peek(a, A, Q.Queue.from_list(a, A, h <> t)) == Some{h} : Maybe }
# length(empty) is 0.
law length_empty:
for -a: Quant
for -A: Kind(a)
{ Q.Queue.length(a, A, Q.Queue.empty(a, A)) == 0n : Nat }
# length(Q{f,r}) is |f| + |r|.
law length_q:
for -a: Quant
for -A: Kind(a)
for f: List
for r: List
{
Q.Queue.length(a, A, Q.Q{f, r})
== Nat.add(List.length(a, A, f), List.length(a, A, r))
: Nat
}
# length after enqueue on a concrete Q{f,r}: |f| + Succ(|r|).
law length_enqueue:
for -a: Quant
for -A: Kind(a)
for f: List
for r: List
for x: A
{
Q.Queue.length(a, A, Q.Queue.enqueue(a, A, Q.Q{f, r}, x))
== Nat.add(List.length(a, A, f), 1n+List.length(a, A, r))
: Nat
}
# length(enqueue(empty, x)) is 1.
law length_enqueue_empty:
for -a: Quant
for -A: Kind(a)
for x: A
{ Q.Queue.length(a, A, Q.Queue.enqueue(a, A, Q.Queue.empty(a, A), x)) == 1n : Nat }
# Definitional characterization of length(from_list(xs)).
law length_from_list_def:
for -a: Quant
for -A: Kind(a)
for xs: List
{
Q.Queue.length(a, A, Q.Queue.from_list(a, A, xs))
== Nat.add(List.length(a, A, xs), List.length(a, A, Nil{}))
: Nat
}
# from_list puts the whole list in front.
law from_list_q:
for -a: Quant
for -A: Kind(a)
for xs: List
{ Q.Queue.from_list(a, A, xs) == Q.Q{xs, Nil{}} : Q.Queue }
# Definitional characterization of to_list(from_list(xs)).
law to_list_from_list_def:
for -a: Quant
for -A: Kind(a)
for xs: List
{
Q.Queue.to_list(a, A, Q.Queue.from_list(a, A, xs))
== List.append(a, A, xs, List.reverse(a, A, Nil{}))
: List
}
# dequeue(empty) is None.
law dequeue_empty:
for -a: Quant
for -A: Kind(a)
{ Q.Queue.dequeue(a, A, Q.Queue.empty(a, A)) == None{} : Maybe> }
# is_empty(empty) is true.
law is_empty_empty:
for -a: Quant
for -A: Kind(a)
{ Q.Queue.is_empty(a, A, Q.Queue.empty(a, A)) == True{} : Bool }
# is_empty(enqueue(empty, x)) is false.
law is_empty_enqueue_empty:
for -a: Quant
for -A: Kind(a)
for x: A
{ Q.Queue.is_empty(a, A, Q.Queue.enqueue(a, A, Q.Queue.empty(a, A), x)) == False{} : Bool }
# is_empty with nonempty front is false.
law is_empty_front_cons:
for -a: Quant
for -A: Kind(a)
for h: A
for t: List
for r: List
{ Q.Queue.is_empty(a, A, Q.Q{h <> t, r}) == False{} : Bool }
# is_empty(from_list(Nil)) is true.
law is_empty_from_nil:
for -a: Quant
for -A: Kind(a)
{ Q.Queue.is_empty(a, A, Q.Queue.from_list(a, A, Nil{})) == True{} : Bool }
# is_empty(from_list(h <> t)) is false.
law is_empty_from_cons:
for -a: Quant
for -A: Kind(a)
for h: A
for t: List
{ Q.Queue.is_empty(a, A, Q.Queue.from_list(a, A, h <> t)) == False{} : Bool }
# norm(empty) is empty.
law norm_empty:
for -a: Quant
for -A: Kind(a)
{ Q.Queue.norm(a, A, Q.Queue.empty(a, A)) == Q.Q{Nil{}, Nil{}} : Q.Queue }
# norm with nonempty front is identity.
law norm_front_cons:
for -a: Quant
for -A: Kind(a)
for h: A
for t: List
for r: List
{ Q.Queue.norm(a, A, Q.Q{h <> t, r}) == Q.Q{h <> t, r} : Q.Queue }
# norm rotates a singleton rear into front.
law norm_rear_singleton:
for -a: Quant
for -A: Kind(a)
for x: A
{ Q.Queue.norm(a, A, Q.Q{Nil{}, x <> Nil{}}) == Q.Q{x <> Nil{}, Nil{}} : Q.Queue }