
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