Why are the brackets required? And what do they signify?
Eg reverse' x:xs = reverse' xs ++ [x] results in a parse error.
So a number of Haskell-specific themes are relevant here, especially if you come from a Lisp background:
* types (but you knew that already!)
* pattern-matching & exhaustivity of matches
* operator infix notation
* associativity precedence
* special notation for lists
It's a good idea to watch out for all of the above when learning the language. It helps to have some google-able names when the situation is ripe for drilling deep into these topics.
To elaborate a bit,
Special List Notation: lists use (:) and [x]. But this syntax is baked specially into the language definition! If you define your own list, it'll typically look like
data List a = Nil | Cons a (List a) -- note the parens!
The alternative GADT-ish style may make this clearer:
data List a where
Nil :: List a
Cons :: a -> List a -> List a
Nil and Cons are data constructor *functions*, and because and only because they are so, do they get to have Capitalized Names. <------- this is another big WTF that trips up many, many learners. Especially with code like:
newtype X a = X a -- whaaaa????? (It's ok, you'll get it soon enough.)
Back to reverse'. With our user-defined List a, reverse' will look like
reverse' Nil =
reverse' (Cons x xs) = ... -- again note the parens!
(There is however, *NO* difference in the semantics. The code just looks different but the compiler doesn't care.)
Note how the pattern-matching includes every single case of the sum-type; here both of them: Nil and Cons. This is Generally A Good Thing!