First of all it is always more readable to write code with guards, instead of if-then-else
. All the extraneous parens are also distracting.
The standard transformation for the inefficient appending-at-end functions, like your
digits n | n < 10 = [n]
| otherwise = digits (quot n 10) ++ [mod n 10]
is to introduce an additional argument, where calling the old digits n ++ xs
is the same as calling the new go n xs
:
digits n = go n [] -- digits_old n ++ [] == go n []
where
go n next | n < 10 = n : next
| otherwise = go (quot n 10) (mod n 10 : next)
-- [a,b,c,...,x,y] [z]
-- [a,b,c,...,x] [y,z]
Thus the digits being produced in the reversed order go one by one into the result list being built bottom-to-the-top in an accumulator parameter, resulting in the list created in the correct order.