Q:

Haskell laziness question with head function

Info:
From Docs and tutorials it says: "Haskell is lazy" by default.
They don't explain the details about it, and i wonder.
Now I know that if I write:
filter odd [1, 2, 3]

It will not filter the results until they are showed or used in expression.
I have a couple of questions about this:

Is the head function lazy?
If not why is it not lazy?
If it is lazy, how does the Haskell compiler know when to execute the function?
I give you an example:
f a b = head a + head b

f [2, 3] [4, 5]

In this case from my perspective head will NOT return 2 + 4.
It will return some type or function that will be executed later when needed. (correct me if i mistaken somewhere).
So my suggestion is that when Haskell see some operation like '+' it calculates the result.
But it gets more complicated because for Integers i suppose if i write 3 + 5 it can be lazy expression as well.
I doubt there are list with functions when the lazy expression starts calculating because it will be hard to write all the variations. 
And last:
f head [1, 2]

Lets say in f function I print the type of the variable passed.
Now how Haskell will know if the Int 1 should be passed or the lazy expression?
Thank you

A:

I think there is some confusion here because the term "lazy" is sometimes used in two different contexts.

lazy semantics (as opposed to eager semantics)
lazy function (which should actually be called non-strict function)

About lazy vs eager semantics: consider this expression
(\x -> 42) (error "urk!")

when the above is evaluated, what is the result?
According to eager semantics, we evaluate the argument before calling the function. The result will be a runtime error.
According to lazy semantics, we call the function immediately. This process can be understood both operationally and denotationally as follows.
Operationally, it is passed a thunk, an object which describes the not-yet-evaluated argument, and which will be "forced" (evaluated) whenever the argument x is needed. We can pretend that x points to the unevaluated expression error "urk!", which will be evaluated when x is demanded.
Denotationally, we use a mathematical trick: we denote the error with a special value called "bottom", and say that error "urk!" has such bottom value.
Then, we simply pretend that this exceptional value can be passed around. In the function call above, x will be bound to "bottom", as if it were a normal value. This is arguably simpler because we do not need to focus on how the expressions are evaluated, but only on how the bottom is propagated.
More precisely, we let "bottom" represent both runtime errors and non-termination (infinite recursion), both of which let a program get away with returning an actual result.
For instance, we have that if bottom then .. else .. will always yield bottom. Similarly for bottom + 4, which is bottom. Again, case bottom of SomeConstructor -> ...; ... is bottom (well, except for newtypes, but let's ignore this). Instead f bottom may or may not be bottom according to what f does: if it needs the argument, the result will be bottom.
About lazy (non-strict) functions. A function f is sometimes said to be "lazy" (or, more properly, non-strict) iff f bottom is bottom.
For instance:
f x = x+1  -- strict / non lazy
f x = 5    -- non strict / lazy
head xs = case xs of   -- strict / non lazy
   [] -> error "head: empty list"
   (x:xs) -> x
g x = (x,True)   -- non strict / lazy

So, since head bottom is case bottom of ... which is bottom, head is not lazy. Operationally, since head demands its argument before producing its result, it is strict / non lazy.
About g: a main feature of lazy semantics is that data constructors like the pair constructor (,) are intrinsically lazy. That is (bottom, 4) is not the same as bottom: this makes it possible to have snd (bottom, 4) = 4 even if the first pair component is an "error" value.
So, g bottom = (bottom, True) is not bottom, and we could apply snd to extract True without triggering the error.

A:

Is the head function lazy?

Yes, Haskell is lazily evaluated by default.

If it is lazy, how does the Haskell compiler know when to execute the function?

The function will be evaluated when the value is needed - which, as far as I understand, ultimately happens when you involve IO in some way.

In this case from my perspective head will NOT return 2 + 4.

Correct, the return 'value' is a so-called thunk, which is another name for an expression not yet evaluated. What's the expression? It's head a + head b.
The main exception from the rule of lazy evaluation is IO, which is eagerly evaluated. So if you want to, say, print the result of calling f [2, 3] [4, 5], then enough of the expression gets evaluated to produce a result to print.
There are ways to force evaluation earlier, if required, e.g. by using seq. This can sometimes be important, because those thunks can get big.

