[Haskell-cafe] Newbie:Debugging and Overgeneralization

Robert Dockins robdockins at fastmail.fm
Mon May 15 12:11:34 EDT 2006


On May 15, 2006, at 11:14 AM, Aditya Siram wrote:

> I have been working with a Haskell text for the past couple of  
> months or so and I have some general problem solving questions.
>
> 1. Is there a way to output intermediate values of a calculation?  
> As an imperative programmer I have become used to using  
> "System.out"'s or 'cout's to check that my function works as  
> intended. I can see no easy way to do that in Haskell. The only  
> solution I could come up with was to avoid using nested functions  
> except for the most trivial expressions and test all expressions in  
> the interpreter. This approach seems to make my code ugly and less  
> readable.

Two responses here:

1) Check out Debug.Trace in the standard libs.  (http:// 
www.haskell.org/ghc/docs/latest/html/libraries/base/Debug- 
Trace.html)  It lets you insert debugging messages into pure code.   
Be warned, its a little tricky to use; your message will only be  
printed _when_and_if_ the thing you "attach" the message to is  
evaluated.

2) I'm not sure exactly what you mean by "nested functions", but  
writing small functions and composing them together to do larger  
tasks is a pretty Haskellish way to approach things.  As you noted,  
this lets you easily test subparts of your computation, and it's  
generally considered good style.  Appropriate use of the composition  
operator (.) or of monads can make function composition more readable.

Creating intermediate representations and writing functions that  
transform data between these representations is a good way to  
structure programs that allows this compositional style.  See: http:// 
www.haskell.org/hawiki/IntermediateRepresentation

> 2. Haskell is great because it makes abstracting from problem very  
> easy. For example, if the problem asks for the area of a square,  
> why not write a function to compute the area of all polygons?  find  
> myself falling into the trap of generalizing to the point that a  
> simple problem becomes quite a bit harder . From a general design  
> perspective should I concentrate on abstracting away just enough to  
> solve the problem or solve the harder problem in the hoping of  
> reusing that code to make life easier in the future?

I'd say, unless you are developing a general-purpose library, solve  
the problem in the simplest (correct!) way first.  One of the nice  
things about Haskell is that its easy to replace code under the hood  
at a later time (pure functional programming is your friend).


For example if you write:

 > areaOfSquare :: Square -> Double
 > areaOfSquare = <special purpose code>


And later you discover you also need:

 > areaOfNPolygon :: NPolygon -> Double
 > areaOfNPolygon = <n-polygon code>


You can replace areaOfSquare with:

 > areaOfSquare = areaOfNPolygon . squareToNPolygon


to reduce duplication, or you can keep the special-purpose code in  
the interests of efficiency.  If you keep the special-purpose code,  
you can use quick check to make sure it gives the same answer as the  
n-polygon routine, which is a nice benefit.



Rob Dockins

Speak softly and drive a Sherman tank.
Laugh hard; it's a long way to the bank.
           -- TMBG



More information about the Haskell-Cafe mailing list