import Base
import ./lib.bend as S
# to_list(empty) is Nil.
law to_list_empty:
for -a: Quant
for -A: Kind(a)
{ S.Stack.to_list(a, A, S.Stack.empty(a, A)) == Nil{} : List }
# empty is S{Nil}.
law empty_is_s_nil:
for -a: Quant
for -A: Kind(a)
{ S.Stack.empty(a, A) == S.S{Nil{}} : S.Stack }
# to_list(S{xs}) exposes the underlying list.
law to_list_s:
for -a: Quant
for -A: Kind(a)
for xs: List
{ S.Stack.to_list(a, A, S.S{xs}) == xs : List }
# push places the new value at the list head.
law to_list_push:
for -a: Quant
for -A: Kind(a)
for xs: List
for x: A
{ S.Stack.to_list(a, A, S.Stack.push(a, A, S.S{xs}, x)) == x <> xs : List }
# push(empty, x) is S{x <> Nil}.
law push_empty:
for -a: Quant
for -A: Kind(a)
for x: A
{ S.Stack.push(a, A, S.Stack.empty(a, A), x) == S.S{x <> Nil{}} : S.Stack }
# pop(push(empty, x)) recovers x and an empty rest.
law pop_push_empty:
for -a: Quant
for -A: Kind(a)
for x: A
{
S.Stack.pop(a, A, S.Stack.push(a, A, S.Stack.empty(a, A), x))
== Some{S.HD{x, S.Stack.empty(a, A)}}
: Maybe>
}
# pop(push(s, x)) recovers x and s.
law pop_push:
for -a: Quant
for -A: Kind(a)
for xs: List
for x: A
{
S.Stack.pop(a, A, S.Stack.push(a, A, S.S{xs}, x))
== Some{S.HD{x, S.S{xs}}}
: Maybe>
}
# pop on a concrete Cons recovers head/rest.
law pop_s_cons:
for -a: Quant
for -A: Kind(a)
for h: A
for t: List
{ S.Stack.pop(a, A, S.S{h <> t}) == Some{S.HD{h, S.S{t}}} : Maybe> }
# peek(push(s, x)) recovers x.
law peek_push:
for -a: Quant
for -A: Kind(a)
for xs: List
for x: A
{ S.Stack.peek(a, A, S.Stack.push(a, A, S.S{xs}, x)) == Some{x} : Maybe }
# peek(push(empty, x)) recovers x.
law peek_push_empty:
for -a: Quant
for -A: Kind(a)
for x: A
{ S.Stack.peek(a, A, S.Stack.push(a, A, S.Stack.empty(a, A), x)) == Some{x} : Maybe }
# peek on Cons recovers head.
law peek_s_cons:
for -a: Quant
for -A: Kind(a)
for h: A
for t: List
{ S.Stack.peek(a, A, S.S{h <> t}) == Some{h} : Maybe }
# is_empty(empty) is true.
law is_empty_empty:
for -a: Quant
for -A: Kind(a)
{ S.Stack.is_empty(a, A, S.Stack.empty(a, A)) == True{} : Bool }
# is_empty(S{Nil}) is true.
law is_empty_s_nil:
for -a: Quant
for -A: Kind(a)
{ S.Stack.is_empty(a, A, S.S{Nil{}}) == True{} : Bool }
# is_empty after push is false.
law is_empty_push:
for -a: Quant
for -A: Kind(a)
for xs: List
for x: A
{ S.Stack.is_empty(a, A, S.Stack.push(a, A, S.S{xs}, x)) == False{} : Bool }
# is_empty(S{h <> t}) is false.
law is_empty_s_cons:
for -a: Quant
for -A: Kind(a)
for h: A
for t: List
{ S.Stack.is_empty(a, A, S.S{h <> t}) == False{} : Bool }
# length(empty) is 0.
law length_empty:
for -a: Quant
for -A: Kind(a)
{ S.Stack.length(a, A, S.Stack.empty(a, A)) == 0n : Nat }
# length(S{xs}) is List.length(xs).
law length_s:
for -a: Quant
for -A: Kind(a)
for xs: List
{ S.Stack.length(a, A, S.S{xs}) == List.length(a, A, xs) : Nat }
# length after push is one plus the prior list length.
law length_push:
for -a: Quant
for -A: Kind(a)
for xs: List
for x: A
{
S.Stack.length(a, A, S.Stack.push(a, A, S.S{xs}, x))
== 1n+List.length(a, A, xs)
: Nat
}
# length(push(empty, x)) is 1.
law length_push_empty:
for -a: Quant
for -A: Kind(a)
for x: A
{ S.Stack.length(a, A, S.Stack.push(a, A, S.Stack.empty(a, A), x)) == 1n : Nat }
# from_list puts the list directly in stack order.
law from_list_s:
for -a: Quant
for -A: Kind(a)
for xs: List
{ S.Stack.from_list(a, A, xs) == S.S{xs} : S.Stack }
# to_list ∘ from_list is identity on lists.
law to_list_from_list:
for -a: Quant
for -A: Kind(a)
for xs: List
{ S.Stack.to_list(a, A, S.Stack.from_list(a, A, xs)) == xs : List }
# from_list ∘ to_list is identity on stacks.
law from_list_to_list:
for -a: Quant
for -A: Kind(a)
for xs: List
{ S.Stack.from_list(a, A, S.Stack.to_list(a, A, S.S{xs})) == S.S{xs} : S.Stack }
# from_list(Nil) roundtrips to empty via to_list.
law to_list_from_empty:
for -a: Quant
for -A: Kind(a)
{ S.Stack.to_list(a, A, S.Stack.from_list(a, A, Nil{})) == Nil{} : List }
# pop(empty) is None.
law pop_empty:
for -a: Quant
for -A: Kind(a)
{ S.Stack.pop(a, A, S.Stack.empty(a, A)) == None{} : Maybe> }
# peek(empty) is None.
law peek_empty:
for -a: Quant
for -A: Kind(a)
{ S.Stack.peek(a, A, S.Stack.empty(a, A)) == None{} : Maybe }