List

A list is a central datastructure in all functional languages. Albatross has a strong functional component and therefore has a list class defined in its base library.

List Type

The module core of the base library defines the class in the following manner.

class
    LIST[A]
create
    []
    (^) (head:A, tail:LIST[A])
end

The operator [] is used to create an empty list. The expression a ^ l adds the element a in front of the list l.

The operator ^ is right associative, i.e. a ^ b ^ l is parsed as a ^ (b ^ l).

The operator ^ is an arithmetic operator which has higher precedence than the addition and the multiplication operators. In order to add 3+4 at the front of a list of naturals parentheses have to be used (3+4) ^ natlist.

Because lists are used frequently there are some shorthands. [A] is a shorthand for LIST[A] and [a,b,c] is a shorthand for a ^ b ^ c ^ [].

The module core does not contain more declarations for lists. More interesting functions are declared in the module list. All the following subchapters explain functions declared in the module list.

Browse the source code of the module list to see the complete user interface.

List Functions

It is possible to extract the first element of a list and tail of a list (i.e. the list without the first element) provided that the list is not empty. The module list defines two partial functions to do this.

head (a:[A]): G
        -- The first element of the list 'a'.
    require
        a as x ^ t
    ensure
        -> inspect
               a
           case h ^ _ then
               h
    end

tail (a:[A]): [A]
        -- The list 'a' with the first element removed.
    require
        a as x ^ t
    ensure
        -> inspect
               a
           case _ ^ t then
               t
    end

Since LIST is a inductive type, recursive functions are easy to define. The module list defines some basic list functions.

(in) (x:G, a:[A]): BOOLEAN
        -- Is the element 'x' contained in the list 'a'?
    -> inspect
           a
       case [] then
           false
       case h ^ t then
           x = h or x in t

elements (a:[A]): {A}
        -- The set of elements of the list 'a'.
    -> {x: x in a}

(+) (a,b: [A]): [A]
        -- The concatenation of the lists 'a' and 'b'.
    -> inspect
           a
       case [] then
           b
       case h ^ t then
           h ^ (t + b)

(-) (a:[A]): [A]
        -- The reversed list 'a'.
    -> inspect
           a
       case [] then
           []
       case h ^ t then
           - t + [h]
Lists and Higher Order Functions

Higher order functions are functions which receive functions as arguments or return functions as results.

We can define a function which receives a list and a function from the list element type to another type and which uses the function to map all elements of the list to generate a new list.

B: ANY

[] (f:A->B, a:[A]): [B]
        -- The list 'a' where all elements are mapped by 'f'.
    require
        a.elements <= f.domain
    ensure
        -> inspect
               a
           case [] then
               []
           case h ^ t then
               f(h) + f[t]
    end

It is very convenient to use the bracket operator [] to define this function because then the expression f[a] maps the whole list a elementwise by the function f and the notation is very intuitive.

Having this function we can map a list of naturals by the successor function.

successor[[0,1,2]] = [1,2,3]

Note that successor is a defined function and not a function object as required by the signature of []. However the compiler converts the function successor into the function object n -> n.successor automatically.

Another interesting higher order function is the function folded which folds a folding function over a list.

A folding function for a list of type [A] is a binary function with the signature [B,A]->B. I.e. it takes a value of type B and a list element of type A and returns a value of type B. The folding needs a start value s and then we get

f.folded(s, [a,b,c])   = f( f( f(s,a), b), c)

The function folded is defined as follows.

folded (f:(B,A)->B, s:B, l:[A]): B
        -- The function 'f' folded with start value 's' over the list 'l'.
    require
        f.is_total
    ensure
        -> inspect
               l
           case [] then
               s
           case h ^ t then
               f.folded(f(s,h), t)
    end

If f is a binary left associative operator op, then we get

(op).folded(s, [a,b,c]) =  s op a op b op c

i.e.

(+).folded(a, [b,c,d])  =  a + b + c + d

results matching ""

    No results matching ""