I believe that the assertion that "in the sequence *of lines in the program* you have to state the base case(s) *first*" is a bit too strong, although it is certainly correct to say that termination must be assured. For (a very trivial) example:
dupEvens :: [Int] -> [Int]
| even n = n : n : dupEvens ns
| otherwise = n : dupEvens ns
which behaves as:
*Main> dupEvens [3,1,4,1,5,9,2,6]
[3,1,4,4,1,5,9,2,2,6,6]
the base case for list recursion (the empty list) is stated last. That is not a problem because the inductive case (non-empty list) contains a pattern that won't match an empty list.
So I suggest modifying the beginners' advice to something like:
When evaluating a function, Haskell considers the parts of the definition in the order they are written, top-to-bottom, and uses the first one that matches. So make sure that your left-hand sides (patterns or guards) are precise enough to select the correct right-hand side is evaluated.
The (trivial and horrible) example:
badDupEvens :: [Int] -> [Int]
| even (head ns) = (head ns) : (head ns) : badDupEvens (tail ns)
| otherwise = (head ns) : badDupEvens (tail ns)
violates that advice, and gets its just desserts:
*Main> badDupEvens [0..5]
[0,0,1,2,2,3,4,4,5*** Exception: Prelude.head: empty list
And, (again for us beginners) a good tip to help avoid such things is to place:
{-# OPTIONS_GHC -Wall #-}
at the beginning of each source file. This allows the compiler to complain at me:
trivialdemo.hs:12:1: Warning:
Pattern match(es) are overlapped
In an equation for ‘badDupEvens’: badDupEvens [] = ...
which (if I'm paying attention) makes me think about my patterns a bit more.
For what it's worth, I tend to try to make my patterns and guards precise enough that they can prevent divergence without too much reliance on lexical ordering. I picked up that habit almost 40 years ago, thanks to Dijkstra's "guarded command" notation in A Discipline of Programming.
I don't know to what extent that is (or isn't) idiomatic in the Haskell community.