Miranda errors (Adapted from Miranda: The Craft of Functional Programming by Simon Thomson) The programs we write all too often contain errors. On encountering an error, the Miranda system either halts, and gives an error message, or continues, but gives a warning message to tell us that something unusual has happened, which might signal we have made an error. We look at a selection of the messages output by Miranda; we have chosen the messages which are both common and require some explanation; message like “otherwise” must be last case ATTEMPT TO TAKE HD OF [] Are self-explanatory. The messages are classified into roughly distinct areas. Syntax errors show up malformed programs, whilst type errors show well-formed expression can often show itself as a type error and not as a syntax error, so the boundaries are not clear. Syntax errors The Miranda system attempts to match the input we give to the syntax of the language. Commonly, when something goes wrong, we type something unexpected. Typing ‘2=3)’ will provoke the error message syntax error – unexpected token ‘)’ Missing parts of a definition are signalled in the obvious way, with messages like missing guard while the inclusion of type declarations or definitions in a where clause are signalled by ‘==’ encountered in local defs An important error message from the definition syntax is syntax error: unreachable case in defn of “fishcake” Which points to a situation like fishcake x (b:y) = … (1) fishcake x [] =… (2) fishcake z w =… (3) in which (1) deals with a non-empty list as second argument, and (2) with an empty list; these cover all the possibilities and so the equation (3) can never be ‘reached’. Errors like this often come from mis-typing: perhaps in (2) we meant to type fishcake (a:x) [] on the left-hand side. The syntax of patterns is more restricted than the full expression syntax, and so we get error messages like inappropriate use of “+” in pattern When we give an over-complicated pattern involving numbers. In specifying constants, we can make errors: floating point numbers can be too large, and characters specified by an out-of-rang ASCII code: syntax error: out-of-range char const (‘\999’) floating point number out of range Not every string can be used as a name; some words in Miranda are keywords, and will give an error if used as an identifier. The keywords are Abstype div if mod otherwise readvals show type where with Other definitions are built into the standard environment- see Appendix G- and so if re-defined will give error messages, thus: syntax error: type of … already declared (in standard environment) The final restriction on names is that names of constructors must being with a capital letter; nothing else can do so, and hence we get error messages like upper case identifier cannot be used as typename Type errors As we have seen in the body of the text, the main type error we meet is exemplified by the response to typing 4 + True: type error in expression cannot unify bool with num which is provoked by using a bool where a num is expected. To locate the source of such an error in general, we have to look for a function which expects a num, but is supplied with a bool. As we said before, we can get type errors from syntax errors. For example, writing abs -2 instead of abs (-2) gives error message cannot unify num->num with num Because it is parsed as 2 subtracted from abs::num->num, and the operator ‘-’ expects a num, rather than a function of type num->num. Other common errors are cannot unify num with [*] cannot cons [num] to [num] given by 2++[2] and [2]:[2], which confuse the roles of ‘:’ and ‘++’. We always give type declarations for our definitions; one advantage of this is to spot when our definition does not conform to its declared type. For example, myCheck :: num -> bool myCheck n = n+0 gives the error message incorrect declaration (line … of script …) specified, myCheck :: num->bool inferred, myCheck::num->num Without the type declaration the definition would be accepted, only to give an error (presumably) when it is used. The show function, which will give a printable version of objects that are not functions, must always be sued in a monomorphic way; failure to do so will give the message use of “show” at polymorphic type A final error related to types is given by definitions like tree == (num,tree,tree) (*) A recursive type synonym; these are signalled by error: cycle in type “==” definition The effect of (*) can be modelled by the algebraic type definition tree ::= Node num tree tree Which introduces the constructor Node to identify objects of this type. Program errors Once we have written a correct script, and asked for the value of an expression which is itself acceptable, other errors can be produced during the evaluation of the expression. The first class of errors comes from missing cases in definitions. If we have written the definition ourselves, we get program error: missing case in definition of … Whilst some of the functions in the standard environment have their own error messages: fold11 applied to [] ATTEMPT TO TAKE t1 OF [] Other errors happen because an arithmetical constraint has been broken. These include an out-of-range list index, division by zero, using a fraction where an integer is expected and floating point calculations which go out of rang: subscript out of range attempt to divide by zero program error: fractional number where integer expected floating point number out of range If we make a conformal definition, like [a,b] = [1…10] this will fail with program error: lhs of definition doesn’t match rhs if the left-hand side fails to match the value on the right; that is clearly the situation here, where the right-hand side has ten elements. Evaluation in Miranda is by need, and so a script which uses a name with no corresponding for the name will not be in error; only if the value of that name is required will we get the message UNDEFINED NAME - .. Finally, if we write a definition like c=c, an attempt to evaluate c gives no result; some recursions, such as c = d where d=d can be detected as being circular, and an attempt to evaluate c gives BLACK HOLE Before halting evaluation. Module errors The %include and %export statements can provoke a variety of error messages: files may not be present, or may contain errors; names may be included more than once, or an alias on inclusion may cause a name clash. The error messages for these and other errors are self-explanatory. Warnings Various situations are acceptable, but may indicate that something is wrong with a script. Among these are: - Specifying the type of an object, but giving it no definition. This is signalled by the message SPECIFIED BUT NOT DEFINED: … - Failing to give any information about an object. This is signalled by the message WARNING, SCRIPT CONTAINS UNDEFINED NAMES: … - Local definitions which are not used. The combination of this with an ‘UNDEFINED’ message often signals that a name has been mis-typed: the name we should use is unused, whilst the name we do use is undefined. Various warnings are also generated by the module system; their meaning is clear. Top-level errors Apart from the syntax errors of mis-typed commands, and commands with missing arguments, like ‘??’, readvals and $+ give rise to various errors if the type of the input expressions is incorrect. Typical messages are data has wrong type :: readvals: bad data in file “%s” System messages In response to some commands and interrupts, the system generates messages, including <<compilation interrupted>> <<interrupt>> signalling the interruption of the current task, <<not enough heap space – task abandoned>> which shows that the space consumption of the evaluation exceeds that available. One way around this is to increase the size of the heap. Typing /heap gives the current size, and /heap 100000 changes the heap size to 100000, if possible, replying with heaplimit = 100000 cells If not, the message illegal value (heap unchanged) will be returned. If the /count command is performed, after each evaluation the system prints diagnostic information of the form reductions = 2004, cells claimed = 530564 no of gc’s = 5, cpu = 19.02 The number of reductions corresponds to the number of steps in our calculations, the cells claimed to the total space usage and the cpu to the time (in seconds) used by the central processing unit of the computer system. Space can be re-cycled after it is no longer used; the garbage collector performs this task when it is necessary, and the no of gc’s indicates how many garbage collections have taken place during evaluation. A measure of the space complexity of a function, as described in Chapter14, is given by the size of the smallest heap in which the evaluation can take place; there is no direct measure of this given by the system.
© Copyright 2026 Paperzz