In imperative languages--and also in some functional languages--expression evaluation
is strict and immediate. If you write x = y+z; in C, for example, you are telling the
computer to perform a computation and put a value into the memory called 'x' right
now! (whenever the code is encountered). In Haskell, by contrast, evaluation is
lazy--expressions are only evaluated when, and as much, as they need to be (in fairness,
C does include shortcutting of Boolean expressions which is a minor kind of laziness).
The definitions of f and g in the example show a simple form of the difference.
While a function like g is somewhat silly, since y is just not used, functions with pattern
matching or guards will very often use particular arguments only in certain
circumstances. If some arguments have certain properties, those or other arguments
might not be necessary for a given computation. In such cases, the needless
computations are not performed. Furthermore, when lists are expressed in
computational ways (list comprehensions and enumeration ellipsis form), only as many
list elements as are actually utilized are actually calculated.