You don't quote the error messages or say which compiler you're using. Here's what I get from SML/NJ:
3867615/john316.sml:7.25-7.64 Error: operator and operand don't agree [tycon mismatch]
operator domain: int list
operand: int
in expression:
answer x
3867615/john316.sml:7.25-7.64 Error: operator and operand don't agree [circularity]
operator domain: 'Z * 'Z list
operand: 'Z * 'Z
in expression:
(findAll f) l :: (findAll f) r
3867615/john316.sml:7.25-7.64 Error: argument of raise is not an exception [tycon mismatch]
raised: _ list
in expression:
raise (answer x :: (findAll <exp>) l :: (findAll <exp>) r)
3867615/john316.sml:9.9-9.37 Error: operator and operand don't agree [circularity]
operator domain: 'Z * 'Z list
operand: 'Z * 'Z
in expression:
(findAll f) l :: (findAll f) r
The first error should be fairly clear: answer
is declared as expecting an int list
argument, but answer x
uses an x
which comes from a Node
and must be an int
. The third error is probably a precedence problem: you can see how the compiler parsed your expression, and it's probably not what you intended. (But what you intended doesn't make sense, as I'll explain below.)
The second and fourth error are due to your confusing the ::
(“cons”) constructor, which adds an element at the front of a list, with the @
(“append”) operator, which concatenates two lists.
Now I'm coming back to the answer
exception. What is it for? Your function must find all occurrences, so it has to traverse the whole tree. There is no circumstance which would require you to return early. Thus you don't need an exception. You've basically got the algorithm right (in an empty tree, there is no match so return the empty list; in a node, prepend the match to the result of the recursive call if present), just don't complicate things.
Making the two corrections, we get the following code (which compiles):
fun findAll f Empty = []
| findAll f (Node(x, l, r)) =
if f x then x :: findAll f l @ findAll f r
else findAll f l @ findAll f r