functional-programminglanguage-lawyermodemercury

What is a "strongly moded" programming language?


I was looking through the Mercury programming language's about page when I found a part where it said:

Mercury is a strongly moded language

What does this mean!? I've search all over the internet, and have found no answer!


Solution

  • I do not know of any other language that has modes as used in Mercury. The following is from the mercury manual

    The mode of a predicate (or function) is a mapping from the initial
    state of instantiation of the arguments of the predicate (or the
    arguments and result of a function) to their final state of
    instantiation.
    

    If you are familiar with prolog you may know what this means.

    Consider a function in C with the following typedecl

    void sort(int * i, int * o);
    

    Assume this function sorts the array i into another array o. Just from this declaration we have no guarantee that i is read from and o is written to. If we can write additionally mode sort(in, out) that suggests to the compiler that the function sort reads from the first argument and writes to the second argument. The compiler then checks the function body to assure us that no writing to i and reading from o takes place.

    For a language like C this may not be suitable, but for a prolog family language this is a very welcome feature. Consider the append/3 predicate which succeeds when the first two lists concatenated is the third list.

    append([1, 2], [a, b], X).
    X = [1, 2, a, b]
    

    So if we provide two input lists we get an output list. But when we provide the output list and ask for all solutions that result in it, we have

    append(X, Y, [1, 2, a, b]).
    X = [],
    Y = [1, 2, a, b] ;
    X = [1],
    Y = [2, a, b] ;
    X = [1, 2],
    Y = [a, b] ;
    X = [1, 2, a],
    Y = [b] ;
    X = [1, 2, a, b],
    Y = [] ;
    false.
    

    This append([1], [2], [3]). fails where as append([1], [2], [1, 2]). succeeds. So depending on how we use the predicate, we can have one deterministic answer, multiple answers, or no answer at all. All these properties of the predicate can be declared initially by mode declarations. The following is a mode declaration for append :

    :- pred append(list(T), list(T), list(T)).
    :- mode append(in, in, out) is det.
    :- mode append(out, out, in) is multi.
    :- mode append(in, in, in) is semidet.
    

    If you provide the first two, the output is deterministically determined. If you provide the last argument, then the you have multiple solutions to the first two arguments. If you provide all three lists, then it just checks if when the first two are appended we get the third list.

    Modes are not restricted to in, out. You will see di destructive input and uo unique output when dealing with IO. They just tell us how a predicate changes the instantiations of argument we provided. Outputs change from free variables to ground terms and inputs remain ground terms. So as a user you can define :- mode input == ground >> ground. and :- mode output == free >> ground. and use them, which are exactly how in and out modes are defined.

    Consider a predicate which calculates the length of a list. We do not need the whole list to be instantiated as we know that length([X, Y], 2) is true even when X, Y are free variables. So the mode declaration :- mode length(in, out) is det. is not sufficient as the whole first argument need not be instantiated. So we can also define the instantiatedness of the argument :- inst listskel == bound([] ; [free | listskel]). which states that an argument is listskel instantiated if it is a empty list or a free variable ahead of another listskel list.

    Such partial evaluations also happen in haskell due to its lazy nature e.g, a whole list need not be evaluated to know its length.

    References: modes determinism

    EDIT: From the mercury website Currently only a subset of the intended mode system is implemented. This subset effectively requires arguments to be either fully input (ground at the time of call and at the time of success) or fully output (free at the time of call and ground at the time of success).