
On Sun, 2007-12-02 at 21:54 -0800, Don Stewart wrote:
catamorphism:
On 12/2/07, Don Stewart
wrote: prstanley:
Hi data Tree = Leaf Int | Node Tree Int Tree
occurs :: Int -> Tree -> Bool occurs m (Leaf n) = m == n occurs m (Node l n r) = m == n || occurs m l || occurs m r
It works but I'd like to know if it can be improved in any way.
You could probably get away with:
data Tree = Leaf !Int | Node Tree !Int Tree
but that's a minor issue.
IMO, there's no reason to even think about putting in the strictness annotations unless you've identified this datatype as part of a performance bottleneck in production code. Otherwise, there's no need to clutter your code and your mind with them :-)
Very true ("a minor issue").
I agree that (in this context, beginning learning Haskell) it is a somewhat minor issue. But I disagree that this is something you should ignore until it becomes a problem and I do think that it should be part of learning Haskell. Properly using strictness is an important part of using Haskell. It makes the difference between code that stack overflows and code that doesn't, code that takes 100 seconds and code that takes 10, code that uses 3MB of RAM and code that uses 600. At least the first of these is not, in my mind, the difference between "optimized" and "unoptimized", but rather the difference between correct and incorrect. Writing better code at the beginning is much easier than trying to figure out what the problem is later. Furthermore, writing better code is not more difficult. In this case it merely means adding two characters. Of late, the "rules of thumb" for this sort of thing are becoming more widely known. Such things need to be "instinctively" part of how you write code, much like writing code tail-recursively or not using (++) left associatively. It's not that you should immediately know that this is better, but (more strongly) that you should not even think of the worse ways to begin with in many cases.