packages feed

disco-0.1.0.0: lib/list.disco

using NoStdLib

||| A right fold for lists.
|||   foldr(f, z, [a,b,c]) = f(a, f(b, f(c, z)))

!!!   foldr(~+~, 0, [1,2,3]) == 6
!!!   foldr(~+~, 0, [])      == 0

foldr : (a × b → b) × b × List(a) → b
foldr(f, z, []   ) = z
foldr(f, z, x::xs) = f(x, foldr(f, z, xs))

||| Append two lists into a single list.

!!!   append([], [])           == []
!!!   append([1,2,3], [])      == [1,2,3]
!!!   append([1,2,3], [4,5,6]) == [1,2,3,4,5,6]
!!!   ∀      xs : List(N). append([], xs) == xs
!!!   forall xs : List(N). append(xs, []) == xs

append : List(a) × List(a) → List(a)
append([],    ys) = ys
append(x::xs, ys) = x :: append(xs, ys)

||| Flatten a list of lists into a single list.

!!!   concat [[1,2],[3],[],[4,5,6]] == [1,2,3,4,5,6]

concat : List(List(a)) → List(a)
concat []      = []
concat (l::ls) = append(l, concat ls)

||| Apply a function to each element of a list, returning a new list
||| of the results.  Note, this is here just for illustration
||| purposes; it is much more efficient to use the builtin primitive
||| 'each' function (which also works on bags and sets).

!!!   eachlist(\x.x+1, []       ) == []
!!!   eachlist(\x.2,   "hello"  ) == [2,2,2,2,2]
!!!   eachlist(\x. 5x, [2,4,1,7]) == [10,20,5,35]

eachlist : (a → b) × List(a) → List(b)
eachlist(f, [])    = []
eachlist(f, x::xs) = f(x) :: eachlist(f, xs)

||| Take the first n elements of a list.
!!!   take(1, [true, false, true]) == [true]
!!!   take(3, [true, false]) == [true, false]
!!!   take(0, [true, false]) == ([] : List(Bool))

take : ℕ × List(a) → List(a)
take(0, _)         = []
take(_, [])        = []
take(n+1, x :: xs) = x :: take(n, xs)

||| The length of a list.
!!!   length [true, false, true] == 3
length : List(a) → ℕ
length [] = 0
length (_::l) = 1 + length l

zipWith : (a × b → c) × List(a) × List(b) -> List(c)
zipWith(_, [], _) = []
zipWith(_, _, []) = []
zipWith(f, a::as, b::bs) = f(a, b) :: zipWith(f, as, bs)

filterlist : (a -> Bool) × List(a) -> List(a)
filterlist(_, []) = []
filterlist(p, a :: as) =
  {? a :: filterlist(p, as)  if p a
  ,  filterlist(p, as)       otherwise
  ?}