Typical Errors and Pitfalls in Curry and PAKCS

This page contains a list of typical errors and pitfalls that beginners in programming with PAKCS and Curry often encounter. You will find explanations of them and suggestions how to solve these problems. The problems are divided into the following categories:

Suggestions to improve this page should be sent to Michael Hanus.


 Compilation Errors

Missing string delimiters:
Compiler error message:
...Improperly terminated string constant

Explanation: String constants are not allowed to be longer than one program line, i.e., the newline character "\n" is not allowed in string constants. If the delimiter " at the end of a string is missing, the string constant continues to the next line and, thus, the above lexical error is reported.

Solution: Since strings must not contain line breaks, break longer strings into shorter ones that are concatenated with "++"

Missing operators, delimiters etc. after applications:
Compiler error message:
...Type error in application
...
Type: ...
cannot be applied

Explanation: If you forget an operator (like "f x g y" instead of "f x ++ g y") or a delimiter (like "[1 2]" instead of "[1,2]") after an application, the compiler interprets that next elements as argument of the preceding application. Thus, it might report a type error with "no application possible".

Solution: Correct the program.


 Compilation Warnings

Unreferenced variable:
Compiler warning:
...unreferenced variable "y"

Explanation: In the rule "add x y = x+x", y is an unreferenced variable since it is introduced as an argument but not used in the right-hand side. Since this might be a typo (as in this example), the compiler shows a warning so that the programmer can check whether this non-use of the variable is intended..

Solution: If it is intended, i.e., the arguments are not used in the right-hand side, use anonymous variables. For instance, write the rule for a projection function on triples in the form "first3 (x,_,_) = x".

Overlapping patterns on the left-hand side of program rules:
Compiler warning:
...Warning: function "test.f" is non-deterministic due to non-trivial overlapping rules

Explanation: In typical programs, either all rules defining a function are pairwise exclusive or there are multiple right-hand sides (e.g., with non-comparable conditions) for the same pattern. Since a non-trivial overlap that does not fall into these categories occurs seldom in application programs and is often an unintended error, the compiler warns about such overlaps. For instance, this warning is produced for the following program:

f 0 = 0
f n = 1

Solution: Ignore the warning (or set "warnoverlapping=no" in your .paksrc to suppress these kind of warnings) if the overlapping is really intended. Otherwise, change the code, e.g., into

f x | x==0      = 0
    | otherwise = 1

Shadowing of symbols:
Compiler warning:
...shadowing symbol "x"

Explanation: As an example, consider the function

f x = g (2*x)
  where
     g x = x+10
In this case, the variable "x" introduced in the local definition of the function g shadows the variable with the same name introduced in the left-hand side of the function definition. Since this is unintended in some cases, the compiler generates a warning.

Solution: Rename shadowed variables.


 Run-time Errors

No solution found:
Run-time message:
...No more solutions.

Explanation: This message indicates that PAKCS was not able to find a (further) solution to the main goal. If logic programming features (i.e., search for solutions) are used, this result shows that there is no solution. However, in purely functional computations, this message indicates an error (since one usually expects a result). The reason can be a partially defined function or a failure in a unification. For instance, consider the following function definitions:

f x | x>0 = 1
    | x<0 = (-1)

g (x:xs) = x:x:xs
Then the evaluation of (f 0) as well as (g []) produces no solution.

Solution: Complete the definition of the function if possible. In order to find the failed function calls in a large computation, use the option ":set +consfail" in PAKCS.

Program interruption:
Run-time message:
...Prolog interruption (h for help)?

Explanation: You have probably interrupted the execution of your Curry program with Control-C. Unfortunately, the current implementation cannot catch this interruption but it is caught by the underlying Prolog system so that you see this message.

Solution: Type "a" followed by the ENTER key in order to abort the (Prolog) execution. When you see the top-level prompt of Prolog ("| ?-"), type "main." to get again the top-level prompt of PAKCS, or type "halt." or Control-D to terminate the complete system and restart PAKCS.

Non-determinism in I/O actions:
Run-time message:
...ERROR: non-determinism in I/O actions occurred!

Explanation: You have executed a program performing I/O that behaves non-deterministically, i.e., that could execute two alternative I/O actions. This is forbidden in Curry since it is not clear how the program should proceed. Therefore, the Curry run-time system checks (after executing an I/O action) where there is an alternative I/O action to execute and aborts with the error message above if this is the case. For instance, consider the following function definition:

ab = 'a'
ab = 'b'
Then the execution of the I/O action "putChar ab" leads to this error message.

Solution: Avoid unintended non-determinism in function definitions (see also overlapping patterns in left-hand sides). You can test all functions in a module for overlapping left-hand sides in PAKCS with the command ":analyze<RETURN>functions". If the non-determinism is intended (for instance, to search for solutions), encapsulate this search by a search operator provided in the module AllSolutions.


 Pitfalls in HTML Programming

Wrong permissions:

Problem: You have written a dynamic web page with the Curry/PAKCS library HTML, but when you access the web page, you get the following message in your web browser:
...access forbidden...

Explanation: This message indicates that the web server has no access to your installed CGI program.

Solution: Make sure that your CGI program is executable by the web server (this depends on its actual installation). In most cases, you must enable the access for everybody (e.g., "chmod 755 ..." in Unix/Linux). Note that you must also provide access to the complete path, e.g., if you store the CGI programs in some subdirectory of your home directory, the home directory must be also accessible!

"No more solutions" in HTML programs

Problem: You have written a dynamic web page with the Curry/PAKCS library HTML, but when you access the web page, you see the following message in your web browser instead of the expected HTML document:
...No more solutions

Explanation: This is a run-time error of your Curry program since it should produce a result document (compare the run-time error "No solution found" described above).

Solution: You cannot interactively debug the computation of a dynamic web page. However, you can generate the CGI program with the option "-debug", i.e., by the command "makecurrycgi -debug ...". This has the effect that some debug code is inserted into the generated CGI program. Hence, you can see the trace of all failed subexpressions in the browser (but not formatted as HTML so that you should view the source of the generated page with your browser). For more details see the Curry Tutorial.

Multiple CGI References in an HTML Document

Problem: The access to your dynamic web page fails with the message "No more solutions" (see above). When you debug the page, you see some thing like
...unreducible expression ('1'=:='2')

and
...unreducible expression ("FIELD_1" =:= ...)

Explanation: This message indicates that you have used the same CGI reference to refer to two different input elements in your HTML document. Since CGI programming in Curry uses logical variables (see also the usage of the data type CgiRef), the unintended use of the same logical variables as two different CGI references results in a unification failure as shown above.

Solution: Make sure that you use a fresh logical variable for every CGI reference.


 Unusual Execution Behavior

Guard vs. local declaration:

Problem: You have a piece of code that executes more slowly than you expect or would like. Sometimes, it is just a lengthy computation, but you should check whether you use a guard in the place of a local declaration.

Examples:

    sort1 x | y =:= permute x & sorted y = y where y free
    sort2 x | sorted y = y where y = permute x 
Both sort1 and sort2 sort an input list using a rather inefficient algorithm, but, e.g., with argument [0,8,9,7,15,13,11,1] sort2 is over 100 times faster than sort1.

Explanation: The difference in execution time originates from the fact that sort1 fully computes a permutation of the argument before checking whether it is sorted. Instead, sort2 computes a permutation of the argument only as much as needed to check whether it is sorted.

Solution: As sort2 shows, do not use a guard as a substitute for a local declaration.

Order of evaluation of built-in operators:

Problem: The order of evaluation should not matter in a declarative language. In particular, most computations in Curry adopt an optimal order of evaluation, without programmer intervention. However, in PAKCS, the order of evaluation of built-in operators, e.g., the addition of integers, is fixed from left to right. In rare cases, this may affect the outcome.

Example:

    f [] = 2

    g x | x==[] = 2

    tr = f x + g x where x free
    tl = g x + f x where x free
The functions f and g are similar, except that f uses pattern matching to check its applicability, whereas g uses a condition with an equality test. Thus, if the argument is an unbound variable, f instantiates the argument to [] whereas g suspends.

Explanation: The evaluation of tr returns 4, as one would expect. However, the evaluation of tl suspends. If an argument of the operator "+" suspends, the evaluation of the entire expression suspends. In the case of tr, the evaluation of the left argument of "+" binds 2 to x so that the right argument evaluates to 2 as well.

Solution: Make sure that you understand the order of evaluation of expressions involving built-in operators.


Barbara Bennemann, Michael Hanus