### Towards NF and WHNF

You all know the `length`

function, right? One possible definition is the following (tail-recursive).

```
length1 :: [a] -> Int
length1 l = go l 0
where go [] acc = acc
go (x:xs) acc = go xs (acc+1)
main = putStrLn ("length1 [1, 2, 3] = " ++ show (length1 [1,2,3]))
```

You probably have used it too, but in case you haven’t, it just computes the length of a list - so here it will return `3`

.

It seems to “deconstruct” the list by pattern matching on it, kind of forcing the evaluation of the list it is passed, not caring about how that list is produced, somehow being *strict* in its argument. So, passing it an infinite list will not terminate, right? Indeed it won’t.

Now let’s imagine we want to compute the length of a (finite, this time) list of numbers. If one of these numbers is our friend `product [1..]`

, it won’t terminate either right? Let’s use the following code to figure out.

```
length1 :: [a] -> Int
length1 l = go l 0
where go [] acc = acc
go (x:xs) acc = go xs (acc+1)
main = let x = product [1..] in print (length1 [1, x])
```

It prints `2`

!

Uh?! What happened? Wasn’t length supposed to evaluate its argument? Well, it did, *up to some point*. Remember, GHC will only evaluate what’s really necessary here. To make sense of this, let’s first remember how the `[a]`

type is defined (almost, since it gets a special treatment syntax-wise).

```
data [] a = [] | (:) a [a]
-- or alternatively, a definition you can actually give to GHC:
data List a = Cons a (List a) | Nil
```

So what we are doing in `length1`

is somehow evaluating the list, isn’t it? Well, not exactly. Let’s examine how `length1 [1, x]`

gets computed.

```
length1 [1, x]
= length1 1:(x:[]) -- just rewriting for clarity
= 1 + length1 (x:[]) -- 1:(x:[]) satisfies the (x:xs) pattern, so that clause gets chosen
= 1 + 1 + length1 [] -- the very same goes for (x:[])
= 1 + 1 + 0 -- [], however, satisfies the first pattern, that of the empty list
= 2
```

This is all nice, but how is this helping us understand why length didn’t care we gave it a list whose second element was a computation that doesn’t terminate? Well, take another look at the evaluation of `length [1, x]`

. Where/when did we actually need to know what values are stored in the list? We didn’t at all. So we’re evaluating, at each recursive step, if the list is the empty list or `x:xs`

for some `x`

and `xs`

, but we’re not evaluating anything further than this.

Now, imagine we want a weird `length`

function, that will only account for the positive numbers stored in the list. That is, we want `weirdLength [-1, 1, 2] == 2`

for example, and `weirdLength`

would behave just like `length`

for lists containing only positive numbers. Let’s write this function.

```
weirdLength :: [Int] -> Int
weirdLength [] = 0 -- nothing surprising here,
-- just like before
weirdLength (x:xs) | x < 0 = weirdLength xs -- negative number, we do not
-- account for it
| otherwise = 1 + weirdLength xs -- positive number, we add one to the "length of the rest of the list"
main = let x = product [1..] in print (weirdLength [1, x])
```

This time, we’re actually taking a look at what the values stored in the list look like, so this time `weirdLength [1,x]`

won’t terminate because the evaluation happens as follows:

```
weirdLength [1, x]
= weirdLength 1:(x:[]) -- just rewriting for clarity
= 1 + weirdLength (x:[]) -- 1:(x:[]) satisfies the (x:xs) pattern, and 1 is positive,
-- so we enter the last clause
= 1 + ???
-- x:[] matches the second pattern (x:xs), but is x negative?
-- We don't know unless we compute it, which the
-- runtime does... but it will never terminate.
```

As opposed to the usual `length`

, we are evaluating everything there is in this list. Of course, the same goes for any of your algebraic data types. Consider the definition of `Maybe`

and an accompanying function `isNothing`

.

```
-- Maybe is defined as:
-- data Maybe a = Nothing | Just a
isNothing :: Maybe a -> Bool
isNothing Nothing = True
isNothing (Just _) = False
main = let x = product [1..] in do
print $ isNothing Nothing
print $ isNothing (Just 4)
print $ isNothing (Just x)
```

Of course, `isNothing Nothing`

returns `True`

, `isNothing (Just 4)`

returns `False`

. But what does `let x = product [1..] in isNothing (Just x)`

return? Does it even return? **It does**, and returns False, because it doesn’t need to inspect what’s actually sitting inside the `Just`

constructor.

Admittedly, this discussion has been quite informal so far; there are more formal ways to talk about the different “dephts” to which we can evaluate expressions.

*Normal form* (NF): An expression in normal form has been fully evaluated, there’s nothing that has been left unevaluated. Examples of expressions in NF are
`1`

`"haskell"`

`(2, True, Nothing)`

`\x -> x + 4`

.

*Weak head normal form* (WHNF): An expression in weak head normal form is either a lambda abstraction or an expression that has its outermost constructor determined/evaluated but it may otherwise contain unevaluated sub expressions. Examples of expressions in WHNF are
`(1+1, 2)`

– which can be rewritten as `(,) (1+1) 2`

, so the outermost constructor is `(,)`

`Just (sum [1..10])`

– the outermost constructor here is `Just`

`1 : computePrimesUpTo 100`

– the outermost constructor here is `(:)`

`\x -> 2+2`

– lambda abstraction, whnf doesn’t require to reduce the body

*Note*: an expression in *normal form* also is in *weak head normal form*, considering that if it has been fully evaluated, if it’s a lambda abstraction then we’re good by definition, and if it’s another kind of expression, the outermost constructor is determined among other things, since it’s fully evaluated.

So `length`

and `isNothing`

evaluate their arguments to *WHNF* whereas `weirdLength`

evaluates the list of ints we hand it to *NF*.

*Note:* You may have heard about *Head Normal Form* too, which exists but isn’t implemented in GHC Haskell. You can read more about it here.