toDigitsRev

doubleEveryOther

You are correct to write doubleEveryOther as a recursive function, but ... you don't need to call length on every call!

Think of a way to writing doubleEveryOther but with calling length at most once.

length and reverse

As you become more familiar with Haskell you learn that you should be wary of calling length and reverse on lists. In this case it is not a big deal because the lists involved are very short, but, in general, if you find yourself using these functions a lot it's an indication that you are using the wrong data structure.

As a bonus exercise, see if you can figure out a way to implement the validate function without using length or reverse.

You're on the right track, I think. If I had to pick one general criticism, it would be to watch out for redundant special cases.

In my opinion, the exercise guides you towards making an unnecessary complication in toDigits and doubleEveryOther. Actually, the list of digits from right to left, as produced by toDigitsRev, is the more natural representation to work with. If you work with the list in left-to-right order, then doubleEveryOther needs to look ahead to see whether the list has an odd or even digit count, which is awkward. Therefore, if given free reign, I'd define a doubleEveryOther' that expects right-to-left input instead.

toDigitsRev does not need special cases for 0 and for n < 10. Instead of calling div and mod, use the divMod function to capture both pieces of information from the same calculation.

You don't need a case for sumDigits (x:[]) — it's already covered by sumDigits (x:xs), where xs is the empty list. The way you wrote it is fine, but personally I'd prefer to write it as sum . map sumDigits' so that you can see at a glance that it's performing a sum of some transformed values.