~/bend-docscommunity

list.bend checks

raw source on the hub · import bend-mathlib@0.3.0.0/list.bend as MList

bend-mathlib/list.bend: List lemmas (append, reverse, length, take, drop, map, fold, filter).

3 imports
import Base
import ./nat.bend as MNat
import ./bool.bend as MBool

Laws

law append_nil provedsource · line 7 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> {List.append(a, A, xs, []) == xs : List<a, A>}

The empty list is a right identity for append: xs ++ [] = xs.

law nil_append provedsource · line 22 · raw

@-a:Quant -> @-A:Kind(a) -> @-xs:List<a, A> -> {List.append(a, A, [], xs) == xs : List<a, A>}

The empty list is a left identity for append: [] ++ xs = xs.

law append_assoc provedsource · line 32 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @-ys:List<a, A> -> @-zs:List<a, A> -> {List.append(a, A, List.append(a, A, xs, ys), zs) == List.append(a, A, xs, List.append(a, A, ys, zs)) : List<a, A>}

Append is associative: (xs ++ ys) ++ zs = xs ++ (ys ++ zs).

law length_append provedsource · line 49 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @-ys:List<a, A> -> {List.length(a, A, List.append(a, A, xs, ys)) == Nat.add(List.length(a, A, xs), List.length(a, A, ys)) : Nat}

The length of an append is the sum of the lengths.

law reverse_go_spec provedsource · line 72 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @-acc:List<a, A> -> {List.reverse.go(a, A, xs, acc) == List.append(a, A, List.reverse(a, A, xs), acc) : List<a, A>}

The reverse accumulator loop appends the reversed list to the accumulator.

law reverse_append provedsource · line 94 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @ys:List<a, A> -> {List.reverse(a, A, List.append(a, A, xs, ys)) == List.append(a, A, List.reverse(a, A, ys), List.reverse(a, A, xs)) : List<a, A>}

Reversing an append reverses and swaps the parts: reverse (xs ++ ys) = reverse ys ++ reverse xs.

law reverse_reverse provedsource · line 112 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> {List.reverse(a, A, List.reverse(a, A, xs)) == xs : List<a, A>}

Reversing twice gives the list back.

law length_reverse provedsource · line 131 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> {List.length(a, A, List.reverse(a, A, xs)) == List.length(a, A, xs) : Nat}

Reversing preserves the length.

law foldr_append provedsource · line 141 · raw

@-a:Quant -> @-A:Kind(a) -> @-B:Type -> @-f:(@_:A -> @_:B -> B) -> @xs:List<a, A> -> @-ys:List<a, A> -> @-z:B -> {List.foldr(a, A, B, f, List.append(a, A, xs, ys), z) == List.foldr(a, A, B, f, xs, List.foldr(a, A, B, f, ys, z)) : B}

A right fold over an append folds the first part onto the fold of the second.

law take_append_drop provedsource · line 160 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @n:Nat -> {List.append(a, A, List.take(a, A, xs, n), List.drop(a, A, xs, n)) == xs : List<a, A>}

Taking n elements and appending the rest after dropping n gives the list back.

law length_map provedsource · line 178 · raw

@-A:Type -> @-B:Type -> @-f:(@_:A -> B) -> @xs:List<&1, A> -> {List.length(&1, B, List.map(A, B, f, xs)) == List.length(&1, A, xs) : Nat}

Mapping preserves the length.

law map_append provedsource · line 194 · raw

@-A:Type -> @-B:Type -> @-f:(@_:A -> B) -> @xs:List<&1, A> -> @-ys:List<&1, A> -> {List.map(A, B, f, List.append(&1, A, xs, ys)) == List.append(&1, B, List.map(A, B, f, xs), List.map(A, B, f, ys)) : List<&1, B>}

Mapping over an append maps each part: map f (xs ++ ys) = map f xs ++ map f ys.

law map_map provedsource · line 211 · raw

@-A:Type -> @-B:Type -> @-C:Type -> @-f:(@_:A -> B) -> @-g:(@_:B -> C) -> @xs:List<&1, A> -> {List.map(B, C, g, List.map(A, B, f, xs)) == List.map(A, C, x => g(f(x)), xs) : List<&1, C>}

Mapping twice is mapping the composition: map g (map f xs) = map (g . f) xs.

law take_zero provedsource · line 229 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> {List.take(a, A, xs, 0n) == [] : List<a, A>}

Taking zero elements gives the empty list.

law drop_zero provedsource · line 243 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> {List.drop(a, A, xs, 0n) == xs : List<a, A>}

Dropping zero elements gives the list back.

law take_nil provedsource · line 257 · raw

@-a:Quant -> @-A:Kind(a) -> @-n:Nat -> {List.take(a, A, [], n) == [] : List<a, A>}

Taking from the empty list gives the empty list.

law drop_nil provedsource · line 267 · raw

@-a:Quant -> @-A:Kind(a) -> @-n:Nat -> {List.drop(a, A, [], n) == [] : List<a, A>}

Dropping from the empty list gives the empty list.

law length_take provedsource · line 277 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @n:Nat -> {List.length(a, A, List.take(a, A, xs, n)) == Nat.min(n, List.length(a, A, xs)) : Nat}

Taking n elements leaves min(n, length) of them.

law length_drop provedsource · line 295 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @n:Nat -> {List.length(a, A, List.drop(a, A, xs, n)) == Nat.sub(List.length(a, A, xs), n) : Nat}

Dropping n elements leaves length - n of them.

law take_length provedsource · line 312 · raw

@-A:Data -> @+xs:List<&2, A> -> {List.take(&2, A, xs, List.length(&2, A, xs)) == xs : List<&2, A>}

Taking as many elements as the list has gives the list back.

law drop_length provedsource · line 326 · raw

@-A:Data -> @+xs:List<&2, A> -> {List.drop(&2, A, xs, List.length(&2, A, xs)) == [] : List<&2, A>}

Dropping as many elements as the list has gives the empty list.

law take_take provedsource · line 339 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @n:Nat -> @m:Nat -> {List.take(a, A, List.take(a, A, xs, n), m) == List.take(a, A, xs, Nat.min(n, m)) : List<a, A>}

Taking m from the first n is taking min(n, m).

law drop_drop provedsource · line 360 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @n:Nat -> @-m:Nat -> {List.drop(a, A, List.drop(a, A, xs, n), m) == List.drop(a, A, xs, Nat.add(n, m)) : List<a, A>}

Dropping m after dropping n is dropping n + m.

law reverse_nil provedsource · line 378 · raw

@-a:Quant -> @-A:Kind(a) -> {List.reverse(a, A, []) == [] : List<a, A>}

Reversing the empty list gives the empty list.

law reverse_singleton provedsource · line 387 · raw

@-a:Quant -> @-A:Kind(a) -> @-x:A -> {List.reverse(a, A, [x]) == [x] : List<a, A>}

Reversing a one-element list gives it back.

law length_replicate provedsource · line 397 · raw

@-A:Data -> @n:Nat -> @-x:A -> {List.length(&2, A, List.replicate(A, n, x)) == n : Nat}

Replicating x n times gives a list of length n.

law length_range provedsource · line 412 · raw

@n:Nat -> {List.length(&2, Nat, List.range(n)) == n : Nat}

Range(n) has length n.

law length_zip provedsource · line 430 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @ys:List<a, A> -> {List.length(&1, Pair(A, A), List.zip(a, A, a, A, xs, ys)) == Nat.min(List.length(a, A, xs), List.length(a, A, ys)) : Nat}

Zipping two lists gives the length of the shorter one.

law append_cons provedsource · line 448 · raw

@-a:Quant -> @-A:Kind(a) -> @-x:A -> @-xs:List<a, A> -> @-ys:List<a, A> -> {List.append(a, A, x <> xs, ys) == x <> List.append(a, A, xs, ys) : List<a, A>}

Appending after a cons: (x :: xs) ++ ys = x :: (xs ++ ys).

law length_nil provedsource · line 460 · raw

@-a:Quant -> @-A:Kind(a) -> {List.length(a, A, []) == 0n : Nat}

The empty list has length zero.

law length_cons provedsource · line 469 · raw

@-a:Quant -> @-A:Kind(a) -> @-x:A -> @-xs:List<a, A> -> {List.length(a, A, x <> xs) == 1n+List.length(a, A, xs) : Nat}

A cons is one longer than its tail.

law concat_append provedsource · line 480 · raw

@-a:Quant -> @-A:Kind(a) -> @xss:List<a, List<a, A>> -> @-yss:List<a, List<a, A>> -> {List.concat(a, A, List.append(a, List<a, A>, xss, yss)) == List.append(a, A, List.concat(a, A, xss), List.concat(a, A, yss)) : List<a, A>}

Concatenating an append concatenates each part: concat (xss ++ yss) = concat xss ++ concat yss.

law foldl_append provedsource · line 496 · raw

@-a:Quant -> @-A:Kind(a) -> @-B:Type -> @-f:(@_:B -> @_:A -> B) -> @xs:List<a, A> -> @-ys:List<a, A> -> @-z:B -> {List.foldl(a, A, B, f, List.append(a, A, xs, ys), z) == List.foldl(a, A, B, f, ys, List.foldl(a, A, B, f, xs, z)) : B}

A left fold over an append folds the second part from the fold of the first.

law map_reverse provedsource · line 514 · raw

@-A:Type -> @-B:Type -> @-f:(@_:A -> B) -> @xs:List<&1, A> -> {List.map(A, B, f, List.reverse(&1, A, xs)) == List.reverse(&1, B, List.map(A, B, f, xs)) : List<&1, B>}

Mapping commutes with reversing: map f (reverse xs) = reverse (map f xs).

law all_append provedsource · line 532 · raw

@-a:Quant -> @-A:Kind(a) -> @-f:(@_:A -> Bool) -> @xs:List<a, A> -> @-ys:List<a, A> -> {List.all(a, A, f, List.append(a, A, xs, ys)) == Bool.and(List.all(a, A, f, xs), List.all(a, A, f, ys)) : Bool}

All over an append is all over each part, joined by and.

law any_append provedsource · line 549 · raw

@-a:Quant -> @-A:Kind(a) -> @-f:(@_:A -> Bool) -> @xs:List<a, A> -> @-ys:List<a, A> -> {List.any(a, A, f, List.append(a, A, xs, ys)) == Bool.or(List.any(a, A, f, xs), List.any(a, A, f, ys)) : Bool}

Any over an append is any over each part, joined by or.

law filter_append provedsource · line 566 · raw

@-A:Data -> @-f:(@_:A -> Bool) -> @xs:List<&2, A> -> @ys:List<&2, A> -> {List.filter(A, f, List.append(&2, A, xs, ys)) == List.append(&2, A, List.filter(A, f, xs), List.filter(A, f, ys)) : List<&2, A>}

Filtering an append filters each part.

law contains_append provedsource · line 591 · raw

@-A:Data -> @-eq:(@_:A -> @_:A -> Bool) -> @xs:List<&2, A> -> @-ys:List<&2, A> -> @+x:A -> {List.contains(A, eq, List.append(&2, A, xs, ys), x) == Bool.or(List.contains(A, eq, xs, x), List.contains(A, eq, ys, x)) : Bool}

An append contains x iff either part does.

law length_filter_le provedsource · line 608 · raw

@-A:Data -> @-f:(@_:A -> Bool) -> @xs:List<&2, A> -> {Nat.is_le(List.length(&2, A, List.filter(A, f, xs)), List.length(&2, A, xs)) == True{} : Bool}

Filtering never makes a list longer.

law mem_cons_self provedsource · line 680 · raw

@x:Nat -> @-xs:List<&2, Nat> -> mem(Nat, Nat.is_eq, x, x <> xs)

The head of a cons is a member of it.

law mem_cons_of_mem provedsource · line 690 · raw

@x:Nat -> @y:Nat -> @-xs:List<&2, Nat> -> @h:mem(Nat, Nat.is_eq, x, xs) -> mem(Nat, Nat.is_eq, x, y <> xs)

Membership is preserved when a new head is prepended.

law not_mem_nil provedsource · line 702 · raw

@-x:Nat -> @_:mem(Nat, Nat.is_eq, x, []) -> Empty

Nothing is a member of the empty list.

law mem_append_left provedsource · line 710 · raw

@xs:List<&2, Nat> -> @ys:List<&2, Nat> -> @x:Nat -> @h:mem(Nat, Nat.is_eq, x, xs) -> mem(Nat, Nat.is_eq, x, List.append(&2, Nat, xs, ys))

Membership on the left of an append.

law mem_append_right provedsource · line 721 · raw

@xs:List<&2, Nat> -> @ys:List<&2, Nat> -> @x:Nat -> @h:mem(Nat, Nat.is_eq, x, ys) -> mem(Nat, Nat.is_eq, x, List.append(&2, Nat, xs, ys))

Membership on the right of an append.

law sorted_nil provedsource · line 732 · raw

sorted_by(Nat, Nat.is_le, [])

The empty list is sorted by any comparator.

law sorted_single provedsource · line 739 · raw

@-x:Nat -> sorted_by(Nat, Nat.is_le, [x])

A singleton list is sorted by any comparator.

law sorted_cons_cons_intro provedsource · line 747 · raw

@-x:Nat -> @-y:Nat -> @-t:List<&2, Nat> -> @hxy:0x74bdc843cd4bfb31bb6f7ba1eb38d231/nat.le(x, y) -> @hyt:sorted_by(Nat, Nat.is_le, y <> t) -> sorted_by(Nat, Nat.is_le, x <> y <> t)

A sorted tail with an in-order head is sorted.

law sorted_cons_cons_elim_le provedsource · line 760 · raw

@x:Nat -> @y:Nat -> @-t:List<&2, Nat> -> @h:sorted_by(Nat, Nat.is_le, x <> y <> t) -> 0x74bdc843cd4bfb31bb6f7ba1eb38d231/nat.le(x, y)

The head pair of a sorted cons-cons list is in order.

law sorted_cons_cons_elim_tail provedsource · line 771 · raw

@x:Nat -> @y:Nat -> @-t:List<&2, Nat> -> @h:sorted_by(Nat, Nat.is_le, x <> y <> t) -> sorted_by(Nat, Nat.is_le, y <> t)

The tail of a sorted cons-cons list is sorted.

law sorted_tail provedsource · line 782 · raw

@x:Nat -> @xs:List<&2, Nat> -> @h:sorted_by(Nat, Nat.is_le, x <> xs) -> sorted_by(Nat, Nat.is_le, xs)

A sorted list has a sorted tail.

law append_nil_sym provedsource · line 798 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> {xs == List.append(a, A, xs, []) : List<a, A>}

The empty list is a right identity for append: xs ++ [] = xs, reversed to rewrite toward the simple side.

law nil_append_sym provedsource · line 808 · raw

@-a:Quant -> @-A:Kind(a) -> @-xs:List<a, A> -> {xs == List.append(a, A, [], xs) : List<a, A>}

The empty list is a left identity for append: [] ++ xs = xs, reversed to rewrite toward the simple side.

law append_assoc_sym provedsource · line 818 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @-ys:List<a, A> -> @-zs:List<a, A> -> {List.append(a, A, xs, List.append(a, A, ys, zs)) == List.append(a, A, List.append(a, A, xs, ys), zs) : List<a, A>}

Append is associative: (xs ++ ys) ++ zs = xs ++ (ys ++ zs), reversed to rewrite toward the simple side.

law length_append_sym provedsource · line 830 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @-ys:List<a, A> -> {Nat.add(List.length(a, A, xs), List.length(a, A, ys)) == List.length(a, A, List.append(a, A, xs, ys)) : Nat}

The length of an append is the sum of the lengths, reversed to rewrite toward the simple side.

law reverse_go_spec_sym provedsource · line 841 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @-acc:List<a, A> -> {List.append(a, A, List.reverse(a, A, xs), acc) == List.reverse.go(a, A, xs, acc) : List<a, A>}

The reverse accumulator loop appends the reversed list to the accumulator, reversed to rewrite toward the simple side.

law reverse_append_sym provedsource · line 852 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @ys:List<a, A> -> {List.append(a, A, List.reverse(a, A, ys), List.reverse(a, A, xs)) == List.reverse(a, A, List.append(a, A, xs, ys)) : List<a, A>}

Reversing an append reverses and swaps the parts: reverse (xs ++ ys) = reverse ys ++ reverse xs, reversed to rewrite toward the simple side.

law reverse_reverse_sym provedsource · line 863 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> {xs == List.reverse(a, A, List.reverse(a, A, xs)) : List<a, A>}

Reversing twice gives the list back, reversed to rewrite toward the simple side.

law length_reverse_sym provedsource · line 873 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> {List.length(a, A, xs) == List.length(a, A, List.reverse(a, A, xs)) : Nat}

Reversing preserves the length, reversed to rewrite toward the simple side.

law foldr_append_sym provedsource · line 883 · raw

@-a:Quant -> @-A:Kind(a) -> @-B:Type -> @-f:(@_:A -> @_:B -> B) -> @xs:List<a, A> -> @-ys:List<a, A> -> @-z:B -> {List.foldr(a, A, B, f, xs, List.foldr(a, A, B, f, ys, z)) == List.foldr(a, A, B, f, List.append(a, A, xs, ys), z) : B}

A right fold over an append folds the first part onto the fold of the second, reversed to rewrite toward the simple side.

law take_append_drop_sym provedsource · line 897 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @n:Nat -> {xs == List.append(a, A, List.take(a, A, xs, n), List.drop(a, A, xs, n)) : List<a, A>}

Taking n elements and appending the rest after dropping n gives the list back, reversed to rewrite toward the simple side.

law length_map_sym provedsource · line 908 · raw

@-A:Type -> @-B:Type -> @-f:(@_:A -> B) -> @xs:List<&1, A> -> {List.length(&1, A, xs) == List.length(&1, B, List.map(A, B, f, xs)) : Nat}

Mapping preserves the length, reversed to rewrite toward the simple side.

law map_append_sym provedsource · line 919 · raw

@-A:Type -> @-B:Type -> @-f:(@_:A -> B) -> @xs:List<&1, A> -> @-ys:List<&1, A> -> {List.append(&1, B, List.map(A, B, f, xs), List.map(A, B, f, ys)) == List.map(A, B, f, List.append(&1, A, xs, ys)) : List<&1, B>}

Mapping over an append maps each part: map f (xs ++ ys) = map f xs ++ map f ys, reversed to rewrite toward the simple side.

law map_map_sym provedsource · line 931 · raw

@-A:Type -> @-B:Type -> @-C:Type -> @-f:(@_:A -> B) -> @-g:(@_:B -> C) -> @xs:List<&1, A> -> {List.map(A, C, x => g(f(x)), xs) == List.map(B, C, g, List.map(A, B, f, xs)) : List<&1, C>}

Mapping twice is mapping the composition: map g (map f xs) = map (g . f) xs, reversed to rewrite toward the simple side.

law take_zero_sym provedsource · line 944 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> {[] == List.take(a, A, xs, 0n) : List<a, A>}

Taking zero elements gives the empty list, reversed to rewrite toward the simple side.

law drop_zero_sym provedsource · line 954 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> {xs == List.drop(a, A, xs, 0n) : List<a, A>}

Dropping zero elements gives the list back, reversed to rewrite toward the simple side.

law take_nil_sym provedsource · line 964 · raw

@-a:Quant -> @-A:Kind(a) -> @-n:Nat -> {[] == List.take(a, A, [], n) : List<a, A>}

Taking from the empty list gives the empty list, reversed to rewrite toward the simple side.

law drop_nil_sym provedsource · line 974 · raw

@-a:Quant -> @-A:Kind(a) -> @-n:Nat -> {[] == List.drop(a, A, [], n) : List<a, A>}

Dropping from the empty list gives the empty list, reversed to rewrite toward the simple side.

law length_take_sym provedsource · line 984 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @n:Nat -> {Nat.min(n, List.length(a, A, xs)) == List.length(a, A, List.take(a, A, xs, n)) : Nat}

Taking n elements leaves min(n, length) of them, reversed to rewrite toward the simple side.

law length_drop_sym provedsource · line 995 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @n:Nat -> {Nat.sub(List.length(a, A, xs), n) == List.length(a, A, List.drop(a, A, xs, n)) : Nat}

Dropping n elements leaves length - n of them, reversed to rewrite toward the simple side.

law take_length_sym provedsource · line 1006 · raw

@-A:Data -> @+xs:List<&2, A> -> {xs == List.take(&2, A, xs, List.length(&2, A, xs)) : List<&2, A>}

Taking as many elements as the list has gives the list back, reversed to rewrite toward the simple side.

law drop_length_sym provedsource · line 1015 · raw

@-A:Data -> @+xs:List<&2, A> -> {[] == List.drop(&2, A, xs, List.length(&2, A, xs)) : List<&2, A>}

Dropping as many elements as the list has gives the empty list, reversed to rewrite toward the simple side.

law take_take_sym provedsource · line 1024 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @n:Nat -> @m:Nat -> {List.take(a, A, xs, Nat.min(n, m)) == List.take(a, A, List.take(a, A, xs, n), m) : List<a, A>}

Taking m from the first n is taking min(n, m), reversed to rewrite toward the simple side.

law drop_drop_sym provedsource · line 1036 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @n:Nat -> @-m:Nat -> {List.drop(a, A, xs, Nat.add(n, m)) == List.drop(a, A, List.drop(a, A, xs, n), m) : List<a, A>}

Dropping m after dropping n is dropping n + m, reversed to rewrite toward the simple side.

law reverse_nil_sym provedsource · line 1048 · raw

@-a:Quant -> @-A:Kind(a) -> {[] == List.reverse(a, A, []) : List<a, A>}

Reversing the empty list gives the empty list, reversed to rewrite toward the simple side.

law reverse_singleton_sym provedsource · line 1057 · raw

@-a:Quant -> @-A:Kind(a) -> @-x:A -> {[x] == List.reverse(a, A, [x]) : List<a, A>}

Reversing a one-element list gives it back, reversed to rewrite toward the simple side.

law length_replicate_sym provedsource · line 1067 · raw

@-A:Data -> @n:Nat -> @-x:A -> {n == List.length(&2, A, List.replicate(A, n, x)) : Nat}

Replicating x n times gives a list of length n, reversed to rewrite toward the simple side.

law length_range_sym provedsource · line 1077 · raw

@n:Nat -> {n == List.length(&2, Nat, List.range(n)) : Nat}

Range(n) has length n, reversed to rewrite toward the simple side.

law length_zip_sym provedsource · line 1085 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @ys:List<a, A> -> {Nat.min(List.length(a, A, xs), List.length(a, A, ys)) == List.length(&1, Pair(A, A), List.zip(a, A, a, A, xs, ys)) : Nat}

Zipping two lists gives the length of the shorter one, reversed to rewrite toward the simple side.

law append_cons_sym provedsource · line 1096 · raw

@-a:Quant -> @-A:Kind(a) -> @-x:A -> @-xs:List<a, A> -> @-ys:List<a, A> -> {x <> List.append(a, A, xs, ys) == List.append(a, A, x <> xs, ys) : List<a, A>}

Appending after a cons: (x :: xs) ++ ys = x :: (xs ++ ys), reversed to rewrite toward the simple side.

law length_nil_sym provedsource · line 1108 · raw

@-a:Quant -> @-A:Kind(a) -> {0n == List.length(a, A, []) : Nat}

The empty list has length zero, reversed to rewrite toward the simple side.

law length_cons_sym provedsource · line 1117 · raw

@-a:Quant -> @-A:Kind(a) -> @-x:A -> @-xs:List<a, A> -> {1n+List.length(a, A, xs) == List.length(a, A, x <> xs) : Nat}

A cons is one longer than its tail, reversed to rewrite toward the simple side.

law concat_append_sym provedsource · line 1128 · raw

@-a:Quant -> @-A:Kind(a) -> @xss:List<a, List<a, A>> -> @-yss:List<a, List<a, A>> -> {List.append(a, A, List.concat(a, A, xss), List.concat(a, A, yss)) == List.concat(a, A, List.append(a, List<a, A>, xss, yss)) : List<a, A>}

Concatenating an append concatenates each part: concat (xss ++ yss) = concat xss ++ concat yss, reversed to rewrite toward the simple side.

law foldl_append_sym provedsource · line 1139 · raw

@-a:Quant -> @-A:Kind(a) -> @-B:Type -> @-f:(@_:B -> @_:A -> B) -> @xs:List<a, A> -> @-ys:List<a, A> -> @-z:B -> {List.foldl(a, A, B, f, ys, List.foldl(a, A, B, f, xs, z)) == List.foldl(a, A, B, f, List.append(a, A, xs, ys), z) : B}

A left fold over an append folds the second part from the fold of the first, reversed to rewrite toward the simple side.

law map_reverse_sym provedsource · line 1153 · raw

@-A:Type -> @-B:Type -> @-f:(@_:A -> B) -> @xs:List<&1, A> -> {List.reverse(&1, B, List.map(A, B, f, xs)) == List.map(A, B, f, List.reverse(&1, A, xs)) : List<&1, B>}

Mapping commutes with reversing: map f (reverse xs) = reverse (map f xs), reversed to rewrite toward the simple side.

law all_append_sym provedsource · line 1164 · raw

@-a:Quant -> @-A:Kind(a) -> @-f:(@_:A -> Bool) -> @xs:List<a, A> -> @-ys:List<a, A> -> {Bool.and(List.all(a, A, f, xs), List.all(a, A, f, ys)) == List.all(a, A, f, List.append(a, A, xs, ys)) : Bool}

All over an append is all over each part, joined by and, reversed to rewrite toward the simple side.

law any_append_sym provedsource · line 1176 · raw

@-a:Quant -> @-A:Kind(a) -> @-f:(@_:A -> Bool) -> @xs:List<a, A> -> @-ys:List<a, A> -> {Bool.or(List.any(a, A, f, xs), List.any(a, A, f, ys)) == List.any(a, A, f, List.append(a, A, xs, ys)) : Bool}

Any over an append is any over each part, joined by or, reversed to rewrite toward the simple side.

law filter_append_sym provedsource · line 1188 · raw

@-A:Data -> @-f:(@_:A -> Bool) -> @xs:List<&2, A> -> @ys:List<&2, A> -> {List.append(&2, A, List.filter(A, f, xs), List.filter(A, f, ys)) == List.filter(A, f, List.append(&2, A, xs, ys)) : List<&2, A>}

Filtering an append filters each part, reversed to rewrite toward the simple side.

law contains_append_sym provedsource · line 1199 · raw

@-A:Data -> @-eq:(@_:A -> @_:A -> Bool) -> @xs:List<&2, A> -> @-ys:List<&2, A> -> @+x:A -> {Bool.or(List.contains(A, eq, xs, x), List.contains(A, eq, ys, x)) == List.contains(A, eq, List.append(&2, A, xs, ys), x) : Bool}

An append contains x iff either part does, reversed to rewrite toward the simple side.

law length_filter_le_sym provedsource · line 1211 · raw

@-A:Data -> @-f:(@_:A -> Bool) -> @xs:List<&2, A> -> {True{} == Nat.is_le(List.length(&2, A, List.filter(A, f, xs)), List.length(&2, A, xs)) : Bool}

Filtering never makes a list longer, reversed to rewrite toward the simple side.

Definitions

def internal_reverse_go_append source · line 64 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @-ys:List<a, A> -> @-acc:List<a, A> -> {List.reverse.go(a, A, xs, List.append(a, A, ys, acc)) == List.append(a, A, List.reverse.go(a, A, xs, ys), acc) : List<a, A>}

def internal_reverse_append_go source · line 86 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @-ys:List<a, A> -> @-acc:List<a, A> -> {List.reverse.go(a, A, List.append(a, A, xs, ys), acc) == List.reverse.go(a, A, ys, List.reverse.go(a, A, xs, acc)) : List<a, A>}

def internal_reverse_go_go source · line 104 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @-acc:List<a, A> -> {List.reverse.go(a, A, List.reverse.go(a, A, xs, acc), []) == List.reverse.go(a, A, acc, xs) : List<a, A>}

def internal_length_reverse_go source · line 121 · raw

@-a:Quant -> @-A:Kind(a) -> @xs:List<a, A> -> @-acc:List<a, A> -> @+n:Nat -> @e:{List.length(a, A, acc) == n : Nat} -> {List.length(a, A, List.reverse.go(a, A, xs, acc)) == Nat.add(n, List.length(a, A, xs)) : Nat}

def internal_length_range_go source · line 416 · raw

@+n:Nat -> @acc:List<&2, Nat> -> {List.length(&2, Nat, List.range.go(n, acc)) == Nat.add(n, List.length(&2, Nat, acc)) : Nat}

def internal_filter_put_append source · line 573 · raw

@-A:Data -> @h:A -> @r:List<&2, A> -> @s:List<&2, A> -> @b:Bool -> {List.append(&2, A, List.filter.put(A, h, r, b), s) == List.filter.put(A, h, List.append(&2, A, r, s), b) : List<&2, A>}

def internal_length_filter_put_le source · line 614 · raw

@-A:Data -> @h:A -> @r:List<&2, A> -> @b:Bool -> {Nat.is_le(List.length(&2, A, List.filter.put(A, h, r, b)), 1n+List.length(&2, A, r)) == True{} : Bool}

def internal_or_of_right source · line 637 · raw

@a:Bool -> @-b:Bool -> @hb:{b == True{} : Bool} -> {Bool.or(a, b) == True{} : Bool}

def internal_or_of_or source · line 644 · raw

@a:Bool -> @-b:Bool -> @-c:Bool -> @h:{Bool.or(a, b) == True{} : Bool} -> @k:(@_:{b == True{} : Bool} -> {c == True{} : Bool}) -> {Bool.or(a, c) == True{} : Bool}

def internal_and_left source · line 651 · raw

@a:Bool -> @-b:Bool -> @h:{Bool.and(a, b) == True{} : Bool} -> {a == True{} : Bool}

def internal_and_right source · line 658 · raw

@a:Bool -> @-b:Bool -> @h:{Bool.and(a, b) == True{} : Bool} -> {b == True{} : Bool}

def internal_mem_append_left source · line 665 · raw

@+xs:List<&2, Nat> -> @+ys:List<&2, Nat> -> @+x:Nat -> @h:{List.contains(Nat, Nat.is_eq, xs, x) == True{} : Bool} -> {List.contains(Nat, Nat.is_eq, List.append(&2, Nat, xs, ys), x) == True{} : Bool}

def internal_mem_append_right source · line 672 · raw

@+xs:List<&2, Nat> -> @+ys:List<&2, Nat> -> @+x:Nat -> @h:{List.contains(Nat, Nat.is_eq, ys, x) == True{} : Bool} -> {List.contains(Nat, Nat.is_eq, List.append(&2, Nat, xs, ys), x) == True{} : Bool}

Templates

template internal_map_reverse_go source · line 521 · raw

@-A:Type -> @-B:Type -> @-f:(@_:A -> B) -> @xs:List<&1, A> -> @acc:List<&1, A> -> {List.map(A, B, f, List.reverse.go(&1, A, xs, acc)) == List.reverse.go(&1, B, List.map(A, B, f, xs), List.map(A, B, f, acc)) : List<&1, B>}

template mem source · line 630 · raw

@-A:Data -> @-eq:(@_:A -> @_:A -> Bool) -> @+x:A -> @xs:List<&2, A> -> Data

Membership in a list, as a reusable proposition.

template sorted_by source · line 634 · raw

@-A:Data -> @-le:(@_:A -> @_:A -> Bool) -> @+xs:List<&2, A> -> Data

A list is sorted by a comparator when every adjacent pair is in order.