I tend to prefer where, but I think that guards & function declarations are more readable than giant if-thens and case constructs.
 
"where" can scope over multiple guards, and guards can access things declared in a "where" clause, both of which are important features:
 
f xs | len > 2   = y
     | len == 1  = 0
     | otherwise = -y
  where
     len = length xs
     y = ...
compare to
 
f xs =
    let len = length xs
        y = ...
    in if len > 2 then y
           else if len == 1 then 0
               else -y
 
The indenting hides the structure of the second function.
 
   -- ryan