# Maintaining laziness

(Difference between revisions)

One of Haskell's main features is non-strict semantics, which in is implemented by lazy evaluation in all popular Haskell compilers. However many Haskell libraries found on Hackage are implemented just as if Haskell would be a strict language. This leads to unnecessary inefficiencies, memory leaks and, we suspect, unintended semantics. In this article we want to go through some techniques on how to check lazy behaviour on functions, examples of typical constructs which break laziness without need, and finally we want to link to techniques that may yield the same effect without laziness.

## 1 Checking laziness

undefined, cycles

unit tests

## 2 Laziness breakers

### 2.1 Maybe, Either, Exceptions

The following looks cumbersome:

```let (Just x) = y
in  Just x```
It looks like a complicated expression for
y
, with an added danger of failing unrecoverably when
y
is not
Just
.

...

parsers - leave Maybe where no Maybe is required

### 2.2 Early decision

Another source of too much strictness is Be aware that the following two expression are not equivalent.

```-- less lazy
if b then f x else f y
-- more lazy
f (if b then x else y)```
It is
if undefined then f x else f y
is
undefined
, whereas
f (if b then x else y)
if
f undefined
,

which is a difference in non-strict semantics.

Consider e.g.
if b then 'a':x else 'a':y
.

pattern match on (,) is better than pattern match on (:), because the first one has no alternative constructor

``` laziness encoded in uncurry
```

if then else

### 2.3 Strict pattern matching in a recursion

The implementation of the
partition
function in GHC up to 6.2 failed on infinite lists.

What happened? The reason was a too strict pattern matching.

Consider the following correct implementation:

```partition :: (a -> Bool) -> [a] -> ([a], [a])
partition p =
foldr
(\x ~(y,z) ->
if p x
then (x : y, z)
else (y, x : z))
([],[])```

...

### 2.4 List reversal

Any use of the list function
reverse