What is a "strongly moded" programming language?
Asked Answered
E

2

5

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!

Elenoraelenore answered 27/10, 2020 at 18:2 Comment(1)
Given it seems to inherit from Prolog, en.wikipedia.org/wiki/Prolog#Modes would be relevant.Trichromatism
C
7

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).

Chicane answered 5/11, 2020 at 4:49 Comment(0)
H
1

Modes specify the direction of data-flow, e.g. input or output.

In some languages, the direction of data-flow is fixed, and implicit in the syntax. For example, in most functional languages, function arguments are always input, and function results are always output.

In most logic programming languages, however, the direction of data-flow is determined at run-time. Most logic programming languages are dynamically moded.

In Mercury, the direction of dataflow must be declared, at least at module boundaries. However, a single predicate or function in Mercury can have multiple modes; the compiler resolves the modes at compile time, and generates separate code for each mode.

Mercury also has support for optional dynamic modes with constraint solving. (See https://www.researchgate.net/publication/220802747_Adding_Constraint_Solving_to_Mercury.)
But the default is static modes.

Hurdle answered 25/2, 2021 at 1:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.