About this document This document is designed for those who have read the Mercury documentation, if only enough to pick up some of the nomenclature without which is it extremely hard to describe situations and concepts. This document is split into two sections. The first entitled "How do I (X)?" presents a number of simple scenarios using the Mercury language which should be very familiar albeit very trivial (or even fascile) examples of programming tasks. The second section called "Why does it (X)?" lists a number of error conditions which may be detected and reported by the compiler, for which there is a simple fix. These errors are likely to be ones which are discovered by those in the early stages of experimentation with the Mercury language as they are syntactic in nature or due to incomplete comprehension of the simpler aspects of the Mercury language model. Entries in the first section may also contain a "DID YOU UNDERSTAND?" paragraph toward the end. This part of an entry will pose a number of questions and possibly exercises that the reader may wish to ponder. The aim is to allow the reader to measure, to some extent, the comprehension of the topic and closely related concepts. The aim is to provide a quick reference for some common constructs of Mercury, and a first-aid guide for problems which might be encountered by those in the early stages of learning the language. The other goal in creating this document was to incant it toward a readership familiar with concepts in an imperative language such as C/C++ and Java. Thus, the author hopes that this will also fare as a transition guide for those exploring Mercury and for whom analogies in the imperative world are usefully brought to bear in the exposition. This document probably impinges of the domain of other documents, such as the Mercury FAQ. In time, the content should be factored out into more appropriate documents. -------------------------------------------------------------------------------------------------------- Section A How do I (X)? -------------------------------------------------------------------------------------------------------- H1. PRINT A LIST OF STRINGS? SAMPLE: :- import_module io, list, string. %% ... % Declarations type string_list == list(string). % a list of strings pred print_list(string_list, io__state, io__state). mode print_list(in, di, uo) is det. %% ... % Print a list of strings print_list(StringList) --> ( {StringList = []}, io__write_string("Finished!") ; {Stringlist = [String|OtherStrings]}, io__write_string(String), io__nl, print_list(OtherStrings) ). TO TEST THIS SAMPLE: You would need to write some code (possibly in the main predicate q.v. the tutorial) to create a string_list and then call the print_list predicate. This could be achived with the following 'main' predicate: % Declare a main predicate in the interface section as usual :- pred main(io__state, io__state). :- mode main(di, uo) is det. %% ... % The entry point main --> % Construct a list of strings and call print_list print_list(["one","two","three","four","five"]). DID YOU UNDERSTAND: - What are the io__state terms in the print_list declaration? - What is the meaning of the '-->' in the definition? - Why are two terms in the print_list predicate surrounded with { }? - Can you modify the code to handle lists of floating point numbers? -------------------------------------------------------------------------------------------------------- H2. CREATE AND USE SIMPLE ABSTRACT TYPES? SAMPLE: :- import_module io, string, int. %% ... % Declarations :- type colour ---> colour( int, % red int, % green int % blue ). :- pred print_colour(Colour). :- mode print_colour(in) is det. :- pred print_intensity(Colour). :- mode print_intensity(in) is det. :- pred print_greenness(Colour). :- mode print_greenness(in) is det. %% ... % Print the colour RGB values print_colour(Colour) --> {Colour = colour(Red, Green, Blue)}, io__write_int(Red), io__write_int(Green), io__write_int(Blue). % Print the overall intensity of a colour print_intensity(colour(Red, Green, Blue)) --> io__write_int(Red + Green + Blue). % Print the greenness of a colour print_greenness(colour(_,Green,_)) --> io__write_int(Green). TO TEST THIS SAMPLE: You just need to instantiate a colour and call one of the predicates. Remember that these predicates all do IO and will expand to require the threaded io__state variables (see tutorial for more information). DID YOU UNDERSTAND? - Why did we import a module called 'int'? - What does the term "Colour = colour(Red, Green, Blue)" do? - How come this works even though Colour is an input and therefore already bound? (shouldn't we have written: "colour(Red, Green, Blue) = Colour"?) -------------------------------------------------------------------------------------------------------- ANSWERS TO "DID YOU UNDERSTAND" QUESTIONS: H1: - What are the io__state terms in the print_list declaration? This predicate will be using IO predicates to do the printing. Mercury requires that the 'state of the universe' (io__state) before and after IO operations be maintained. These have to be threaded through all predicates which perform IO. Although the underlying concept is completely different, the mechanism of hiding the declarative impurity of IO is encapsulated in a roughly similar way to how the potential of exceptions is managed in the Java language. Predicates which are affected have to explicitly 'declare' this fact. - What is the meaning of the '-->' in the definition? This is the DCG operator. It tells Mercury to add arguments to predicate 'behind the scenes' to carry some pre and post state into and out of the predicate. The compiler is said to 'expand' the DCG format to add these arguments. In the case of the print_list predicate we need to 'thread' an incoming and outgoing io_state through the predicate in order to 'record' the impact of the IO on the 'world'. See above and q.v. Definite Clause Grammar (DCG) in the Mercury Tutorial. - Why are two terms in the print_list predicate surrounded with { }? Mercury will normally expand ALL terms in a clause defined in the DCG form (see above). This is exactly what we want for those clauses which are handling the extra arguments (in this case the io__state's), but there's logic here that doesn't need to get involved with the extra arguments and these need to be 'escaped' from the DCG expansion. This is accomplished with the curly brace syntax. H2: - Why did we import a module called 'int'? Mercury does not have many features built-in (as an intrinsic part of the language) that are commonly built in to other languages. This is true of even the operators associated with the simple 'scalar types' (int, float, char etc.). Mercury therefore does not have to carry around the 'baggage' associated with these features if they are not used in a program. Conversely though, you do of course have to remember to include them into modules which make use of individual types and features. Failure to do so will result in 'undefined predicate' messages of various kinds. The 'int' module includes the 'standard' operators for manipulating machine-sized integer numbers. In the case of integers, the int type itself is an implicit part of Mercury, but the operators are not. With most abstract types (like a list), then even the list type itself is declared in the library module (along with related operators, functions and predicates). - What does the term "Colour = colour(Red, Green, Blue)" do? This term 'unpacks' the colour which was passed into the predicate into its constituent fields Red, Green and Blue (which are all ints according to the type declaration). - How come this works even though Colour is an input and therefore already bound? (shouldn't we have written: "colour(Red, Green, Blue) = Colour"?) This may look like an assignment statement which is written the wrong way around if you're used to imperative languages. Actually Mercury has no concept of assignment per se, but instead the concept of unification which is used in similar ways, but is quite different. In Mercury, you cannot 'assign' a value to a variable which is already assigned, but you can unify a variable assigned a value (known as a ground variable) with an unassigned variable (called a free variable). The details are rather more complex, and the reader should consult the Mercury references for futher information. In our example though, Mercury will make the term colour(Red, Green, Blue) equivalent to the Colour variable, and because the former term is expanded to show free variables for the fields, these fields (Red, Green, Blue) will take on the values of the hidden fields within the ground Colour variable. ======================================================================================================== Section B Why does it (X)? -------------------------------------------------------------------------------------------------------- W1.Complain about an undefined predicate (with a larger arity than I would expect)? e.g. undefined predicate '=/4'. Assuming that you simply haven't omitted a predicate from your code (!), you may well have forgotten to escape a term in a DCG format clause. Taking the list printing example in H1, the exact error message indicated above will arise if the clause "{StringList = []}" had not been rendered with the curly braces. This would have caused the term to have been expanded to include two new arguments (X0 and X) to the comparator (=) adding to the two that are implied by the infix syntax. However there is no definition of '=' or arity 4 (normally written =/4), only the very sensible definition =/2.