Will I develop good/bad habits because of lazy evaluation?

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:

f x y = if x > y then .. a .. b .. else c
  where
    a = expensive
    b = expensive 
    c = expensive

here we define a bunch of subexpressions in a where clause, 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":

pairs = zip xs [1..]

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 readable

pairs = foldr (\x xs -> \n -> (x,n) : xs (n+1)) (const []) xs 1

or 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.


You'll certainly learn about evaluation strategies. Non-strict evaluation strategies can be very powerful for particular kinds of programming problems, and once you're exposed to them, you may be frustrated that you can't use them in some language setting.

I may develop thought patterns that work in a lazy world but not in a normal order/eager evaluation world.

Right. You'll be a more rounded programmer. Abstractions that provide "delaying" mechanisms are fairly common now, so you'd be a worse programmer not to know them.


  1. I may misinterpret lazy-evaluation-based features as being part of the "functional paradigm".

Lazy evaluation is an important part of the functional paradigm. It's not a requirement - you can program functionally with eager evaluation - but it's a tool that naturally fits functional programming.

You see people explicitly implement/invoke it (notably in the form of lazy sequences) in languages that don't make it the default; and while mixing it with imperative code requires caution, pure functional code allows safe use of laziness. And since laziness makes many constructs cleaner and more natural, it's a great fit!

(Disclaimer: no Haskell or F# experience)