On Tue, Aug 19, 2008 at 02:30:37PM -0400, Barry Burd wrote:
> I'm just getting started with Haskell. I've written the following simple program:
>> module Med
> where
>> -- lst = [5, 3, 7, 8, 0, 2, 4, 1, 6]
> lst = [7, 3, 1, 2, 0, 9, 8]
> numLessThan x = length([y | y <- lst, y < x])
> numGreaterThan x = length([y | y <- lst, y > x])
>> median = [ x | x <- lst, numLessThan x == numGreaterThan x]
>> I realize that this code isn't very robust. My questions are as follows:
> - I remember running this code with some values of lst (containing an odd number of unique integer values) and getting the wrong answer. Is that possible? I can't replicate the results because I don't remember what values of lst didn't work.
It seems to me that you would run into problems with a list containing
an even number of unique integer values. In such a list, there are no
values which have an equal number of greater and lesser values. For
example, if your list has four elements, then any particular element
would have either 0 less than it and 3 greater, or 1 less and 2
greater, or 2 less and 1 greater, etc. If I recall correctly, in such
a case the median is defined as the average of the two centermost
values.
> - How can I add a line or two to display intermediate results (in order to debug the code if necessary)? I've tried adding putTraceMsg but I keep getting parse errors. I probably haven't fully assimilated the syntax of functional programming yet.
You can always import Debug.Trace and use the 'trace' function, which takes a String and another value, and prints the String before returning the other value. So for example, you could say
numLessThan x = length( [ y <- lst, trace (show y ++ " < " ++ show x ++ "?\n") (y < x)] )
to have each test print a message.
*However*, you will probably find that printing intermediate results
is not as useful in Haskell as you are used to in other languages.
For one thing, Haskell's laziness means that things may not be
evaluated in the order you might think, so the order in which things
are printed may be confusing. And in any case, a much better
debugging strategy is to make sure to break things down into many
simple top-level functions which you can test interactively on their
own. The absence of side-effects makes it quite easy to test pieces
of your program separately before putting them together. Using
testing tools like QuickCheck is also a great way to make sure your
functions behave in the way you expect, and to help figure out what is
wrong with them when they don't.
-Brent