Example Project Solution

Define a function called "remove" that delivers those elements of a sequence
supplied as its second argument that are the same as a value supplied as its
first argument.

This project asks you to define a function named "remove".
The project description talks about two arguments for the function
(a "second argument" and a "first argument). From this you can deduce
that the definition of the function would start out with the function
name ("remove") followed by two parameter names (one for each argument
to be supplied to the function).

You decide what names you want to use for the parameters.
The project description doesn't say much about the kind of
data that might be supplied to the function - just that the second
argument is a "sequence" and the first argument is a "value."
It also says that any values in the sequence (which is the second argument)
that are the same as the value (which is the first argument) are to
be removed from the sequence. From this you can conclude that the
first argument and the elements of the sequence supplied as the
second argument are the same kind of data.

Since the description of the arguments has such a generic quality,
your choices for the names of the parameters in the definition
should reflect this lack of specificity. A choice of "x" as the
name of the first argument and "xs" (pronounced "exes," which is
supposed to suggest a bunch of x's) would have a suitably generic
flavor.

With these decisions, you can conclude that the
definition of the function will look something like this:

remove x xs = ... some formula goes here ...

But, what about the right hand side of the definition?
What is "... some formula ..."?
Well, the right hand side of a definition is a formula that specifies the
value to be delivered by the function. In this case,
that value is supposed to be pretty much the
same as the second argument ("xs"), but with a few omissions.

That might suggest using a formula based
on list comprehension (Lesson 5 in the Haskell text) because
list comprehension specifies a new sequence whose elements come
from a given sequence, but with some conditions (guards) on which of
those elements are admissible.

I say "might suggest" more cavalierly than I should.
Deciding what kind of formula
to use to express the value delivered by the
function is the only really creative step in this
project. Mentioning that insight in an off-hand way
is a common stylistic device of mathematicians -
using phrases like "might suggest", as if it might just come upon
you out of nowhere in your sleep, or when you're daydreaming.

To be fair
to the mathematician, the insight may well have come during sleep,
but only after months of deep thought while wide awake. I'm not
suggesting that the insight required to solve problems in this
course
calls for months of deep
thought. A few hours should do nicely for this project.
Or, a few minutes if you've
acquired a thorough understanding of the material of Lessons 1-6 -
or if you get lucky.
But, deciding what type of formula to use on the right-hand-side
of the definition is the crucial step.

After deciding to use a list comprehension,
you can write down a
bit more of the definition:

remove x xs = [y | y guard goes here ...]

That is, you can write this down as soon as you think of a name
to use for a typical element from the sequence xs. I use the name
"y" because (1) the value will be of the same kind as the elements of
the sequence xs, (2) x is a value of that same kind, and (3) it is
traditional in many high-school algebra problems to use the names "x"
and "y" to denote values of the same kind.

Now, the guard is suppose to specify which elements are acceptable
in the sequence denoted by the list comprehension. The project
statement says that the elements acceptable in the sequence
delivered by the function are those elements that are not the same
as the value supplied by the first argument ("x"). So, with that
observation, you can write down the missing guard.

Your Hugs session with your function to illustrate all of these
properties, and your hand-written annotations should specify which
properties each invocation of your function in the session is
supposed to demonstrate. It might look like this:

Script started on Tue Sep 03 09:49:28 1996

... I removed some stuff here ... you shouldn't do this ...

Hugs session for:
/home/rlpage/fnl/hugs3/lib/Prelude.hs
remove.hs

handwritten annotation: example below removes the 't',
leaves all else, including 'T', and in the same order

Main> remove 't' "Triathlon"
"Triaholon"

handwritten annotation: next examples show that multiple
elements are removed if they occur