A Tour of Morfa

Alias templates

Basic use of alias templates is to introduce convenient notation for possibly complex type expressions. For example, you may introduce the name Predicate<T> as an alias for a type of functions taking an argument of type T and returning a bool:

public template <T> alias Predicate = func(T): bool;

The alias may be used in the signature of a generic function filter that takes a predicate and a list and returns a new list consisting of those elements of the given list that satisfy the predicate:

import advanced.templates.class_templates;
import advanced.templates.function_templates;

public template <T>
func filter(test: Predicate<T>, list: List<T>): List<T>
{
    if (length(list) == 0)
        return list;
    var h = list.head;
    var t = filter<T>(test, list.tail);

    return if (test(h)) cons(h, t) else t;
}

unittest
{
    var ints = cons(1, cons(2, cons(3, cons(4, null))));
    var isOdd: Predicate<int> = func(n: int) { return n % 2 == 1; };
    var odds = filter(isOdd, ints);
    assert (odds.head == 1);
    assert (odds.tail.head == 3);
    assert (odds.length() == 2);
}

Here is another example in a similar spirit:

public template <T> alias Comparator = func(T,T): bool;

public template <T>
func findMax(list: List<T>, comparator: Comparator<T>): T
{
    if (length(list) == 0)
        return T.min;

    var h = list.head;
    var max = findMax(list.tail, comparator);
    return if (comparator(h, max)) max else h;
}

unittest
{
    var ints = cons(2, cons(1, cons(3, cons(0, null))));
    var cmptor: Comparator<int> = func(n: int, m: int) { return n < m; };
    var max = findMax(ints, cmptor);
    assert (max == 3);
}

More useful application of alias templates as a tool for type-level programming is described in section on type level programming.