The map and length functions can be defined as follows:
map :: (a -> b) -> [a] -> [b] map _ [] = [] map f (x:xs) = fx : map f xs length :: [a] -> Int length [] = 0 length (_:xs) = 1 + length xs
Now let's find out why your second example works the way it does. This happens as follows:
length (map (`div` 0) (1:2:3:4:[])) = length (1 `div` 0 : map (`div` 0) (2:3:4:[])) -- second map equation = 1 + (length (map (`div` 0) (2:3:4:[]))) -- second length equation = 1 + (length (2 `div` 0 : map (`div` 0) (3:4:[]))) -- second map equation . . . = 1 + (1 + (1 + (1 + length (map (`div` 0) []))))) -- second length equation = 1 + (1 + (1 + (1 + length [])))) -- first map equation = 1 + (1 + (1 + (1 + 0)))) -- first length equation = 4 -- arithmetic
What is the trick here? In Haskell, the process of evaluating an expression is called forced. Forcing an expression does the minimal work necessary to define an external result data constructor. As part of this, subexpressions will be forced only as necessary to achieve the goal.
So, in this example, the outermost expression that we force is the use of the length function. The definition of length has two cases: one that uses the list constructor [] , and the other that uses the constructor (:) , so to apply length we need to figure out which of these two cases applies to the argument. Since the argument has no constructor in its most extreme position, we are forced to figure it out. What happens in the step between the first and second lines of output above; we force the map subexpression by looking at its arguments and choosing the second map equation.
But after this point, we have all the information necessary to determine which of the two equations for length is applied, so we go by the "extreme first" rule and apply the corresponding length equation. In this case, it discards the subexpression that contains the division by zero, which means that the subexpression will never be forced, and the error will never be triggered.
In the first example, however, when entering an expression in GHCI, you implicitly ask the interpreter to print its result. This requires him to make the list spine access its elements and make the elements themselves print them. Thus, division by zero error occurs when you force the first element of the list.
EDIT: Let me point out one nuance that you might not have noticed. When we try your first example in GHCI, this is the result of the session:
*Main> map (`div` 0) [1,2,3,4] [*** Exception: divide by zero
Look at this lone square bracket at the beginning of the second line? This is the opening bracket for the list that was printed before dividing by zero error. Also note what happens in this example:
*Main> map (20 `div`) [1,2,0,4] [20,10,*** Exception: divide by zero
The first two elements of the list of results, and even the comma separating the second element from the third, are successfully printed because Haskell does not try to calculate the third element of the list until it is printed.