union List<T> {
empty
node(T, List<T>)
}
recursive length<E>(List<E>) -> Nat{
length([]) = 0
length(node(n, next)) = 1 + length(next)
}
recursive operator ++<E>(List<E>,List<E>) -> List<E>{
operator ++([], ys) = ys
operator ++(node(n, xs), ys) = node(n, xs ++ ys)
}
recursive reverse<E>(List<E>) -> List<E>{
reverse([]) = []
reverse(node(n, next)) = reverse(next) ++ node(n, [])
}
recursive set_of<T>(List<T>) -> Set<T>{
set_of([]) = ∅
set_of(node(x, xs)) = single(x) ∪ set_of(xs)
}
recursive mset_of<T>(List<T>) -> MultiSet<T>{
mset_of([]) = m_fun(fun x { 0 })
mset_of(node(x, xs)) = m_one(x) ⨄ mset_of(xs)
}
recursive map<T,U>(List<T>,(fn T -> U)) -> List<U>{
map([], f) = []
map(node(x, ls), f) = node(f(x), map(ls, f))
}
recursive foldr<T,U>(List<T>,U,(fn T, U -> U)) -> U{
foldr([], u, c) = u
foldr(node(t, ls), u, c) = c(t, foldr(ls, u, c))
}
recursive foldl<T,U>(List<T>,U,(fn U, T -> U)) -> U{
foldl([], u, c) = u
foldl(node(t, ls), u, c) = foldl(ls, c(u, t), c)
}
recursive down_from(Nat) -> List<Nat>{
down_from(0) = []
down_from(suc(n)) = node(n, down_from(n))
}
fun up_to(n) {
reverse(down_from(n))
}
recursive interval(Nat,Nat) -> List<Nat>{
interval(0, begin) = []
interval(suc(num), begin) = node(begin, interval(num, suc(begin)))
}
fun range(b, e) {
interval(e - b, b)
}
recursive zip<T,U>(List<T>,List<U>) -> List<Pair<T,U>>{
zip([], ys) = []
zip(node(x, xs'), ys) =
switch ys {
case [] {
[]
}
case node(y, ys') {
node(pair(x, y), zip(xs', ys'))
}
}
}
recursive filter<E>(List<E>,(fn E -> bool)) -> List<E>{
filter([], P) = []
filter(node(x, ls), P) =
if P(x) then
node(x, filter(ls, P))
else
filter(ls, P)
}
recursive remove<T>(List<T>,T) -> List<T>{
remove([], y) = []
remove(node(x, xs'), y) =
if x = y then
xs'
else
node(x, remove(xs', y))
}
recursive remove_all<T>(List<T>,T) -> List<T>{
remove_all([], y) = []
remove_all(node(x, xs'), y) =
if x = y then
remove_all(xs', y)
else
node(x, remove_all(xs', y))
}
recursive get<T>(List<T>,Nat) -> Option<T>{
get([], i) = none
get(node(x, xs), i) =
if i = 0 then
just(x)
else
get(xs, pred(i))
}
recursive take<T>(Nat,List<T>) -> List<T>{
take(0, xs) = []
take(suc(n), xs) =
switch xs {
case [] {
[]
}
case node(x, xs') {
node(x, take(n, xs'))
}
}
}
recursive drop<T>(Nat,List<T>) -> List<T>{
drop(0, xs) = xs
drop(suc(n), xs) =
switch xs {
case [] {
[]
}
case node(x, xs') {
drop(n, xs')
}
}
}
fun head<T>(ls:List<T>) {
switch ls {
case [] {
@none<T>
}
case node(x, xs) {
just(x)
}
}
}
fun tail<T>(ls:List<T>) {
switch ls {
case [] {
@[]<T>
}
case node(x, xs) {
xs
}
}
}
length_append: (all U:type, xs:List<U>, ys:List<U>. length(xs ++ ys) = length(xs) + length(ys))
length_zero_empty: (all T:type, xs:List<T>. (if length(xs) = 0 then xs = []))
append_assoc: (all U:type, xs:List<U>, ys:List<U>, zs:List<U>. (xs ++ ys) ++ zs = xs ++ (ys ++ zs))
append_empty: (all U:type, xs:List<U>. xs ++ [] = xs)
length_reverse: (all U:type, xs:List<U>. length(reverse(xs)) = length(xs))
length_map: (all T:type, f:(fn T -> T), xs:List<T>. length(map(xs, f)) = length(xs))
map_id: (all T:type, f:(fn T -> T). (if (all x:T. f(x) = x) then (all xs:List<T>. map(xs, f) = xs)))
map_append: (all T:type, f:(fn T -> T), ys:List<T>, xs:List<T>. map(xs ++ ys, f) = map(xs, f) ++ map(ys, f))
map_compose: (all T:type, U:type, V:type, f:(fn T -> U), g:(fn U -> V), ls:List<T>. map(map(ls, f), g) = map(ls, g ∘ f))
zip_empty_right: (all T:type, U:type, xs:List<T>. zip(xs, []:List<U>) = [])
zip_map: (all T1:type, T2:type, U1:type, U2:type, f:(fn T1 -> T2), g:(fn U1 -> U2), xs:List<T1>, ys:List<U1>. zip(map(xs, f), map(ys, g)) = map(zip(xs, ys), pairfun(f, g)))
set_of_empty: (all T:type, xs:List<T>. (if set_of(xs) = ∅ then xs = []))
set_of_append: (all T:type, xs:List<T>, ys:List<T>. set_of(xs ++ ys) = set_of(xs) ∪ set_of(ys))
mset_of_empty: (all T:type, xs:List<T>. (if mset_of(xs) = m_fun(fun x { 0 }) then xs = []))
som_mset_eq_set: (all T:type, xs:List<T>. set_of_mset(mset_of(xs)) = set_of(xs))
not_set_of_remove_all: (all W:type, xs:List<W>, y:W. not (y ∈ set_of(remove_all(xs, y))))
take_append: (all E:type, xs:List<E>, ys:List<E>. take(length(xs), xs ++ ys) = xs)
length_drop: (all E:type, xs:List<E>, n:Nat. (if n ≤ length(xs) then length(drop(n, xs)) + n = length(xs)))
length_drop_zero: (all E:type, xs:List<E>, n:Nat. (if length(xs) < n then length(drop(n, xs)) = 0))
drop_append: (all E:type, xs:List<E>, ys:List<E>. drop(length(xs), xs ++ ys) = ys)
get_drop: (all T:type, n:Nat, xs:List<T>, i:Nat, d:T. get(drop(n, xs), i) = get(xs, n + i))
get_append_front: (all T:type, xs:List<T>, ys:List<T>, i:Nat. (if i < length(xs) then get(xs ++ ys, i) = get(xs, i)))
get_append_back: (all T:type, xs:List<T>, ys:List<T>, i:Nat. get(xs ++ ys, length(xs) + i) = get(ys, i))
get_none: (all T:type, xs:List<T>, i:Nat. (if length(xs) ≤ i then get(xs, i) = none))
mset_equal_implies_set_equal: (all T:type, xs:List<T>, ys:List<T>. (if mset_of(xs) = mset_of(ys) then set_of(xs) = set_of(ys)))
head_append: (all E:type, L:List<E>, R:List<E>. (if 0 < length(L) then head(L ++ R) = head(L)))
tail_append: (all E:type, L:List<E>, R:List<E>. (if 0 < length(L) then tail(L ++ R) = tail(L) ++ R))