Miranda errors

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.