I’m looking to learn functional programming with either Haskell or F#.
Are there any programming habits (good or bad) that could form as a result Haskell’s lazy evaluation? I like the idea of Haskell’s functional programming purity for the purposes of understanding functional programming. I’m just a bit worried about two things:
- I may misinterpret lazy-evaluation-based features as being part of the “functional paradigm”.
- I may develop thought patterns that work in a lazy world but not in a normal order/eager evaluation world.
There are habits that you get into when programming in a lazy language that don’t work in a strict language. Some of these seem so natural to Haskell programmers that they don’t think of them as lazy evaluation. A couple of examples off the top of my head:
here we define a bunch of subexpressions in a
whereclause, with complete disregard for which of them will ever be evaluated. It doesn’t matter: the compiler will ensure that no unnecessary work is performed at runtime. Non-strict semantics means that the compiler is able to do this. Whenever I write in a strict language I trip over this a lot.Another example that springs to mind is “numbering things”:
here we just want to associate each element in a list with its index, and zipping with the infinite list
[1..]is the natural way to do it in Haskell. How do you write this without an infinite list? Well, the fold isn’t too readableor you could write it with explicit recursion (too verbose, doesn’t fuse). There are several other ways to write it, none of which are as simple and clear as the
zip.I’m sure there are many more. Laziness is surprisingly useful, when you get used to it.