Another idea would be to say: the last digit counts for 1, the next-to last counts for 10, the digit before that counts for 100, etcetera. So to convert a list of digits to a number, you need to reverse it (in order to start at the back), multiply the digits together with the corresponding powers of ten, and add the result together.
To reverse a list, use reverse
, to get the powers of ten you can use iterate (*10) 1
(try it in GHCi or Hugs!), to multiply corresponding digits of two lists use zipWith (*)
and to add everything together, use sum
- it really helps to know a few library functions! Putting the bits together, you get
fromDigits xs = sum (zipWith (*) (reverse xs) (iterate (*10) 1))
Example of evaluation:
fromDigits [1,2,3,4]
==> sum (zipWith (*) (reverse [1,2,3,4]) [1,10,100,1000, ....]
==> sum (zipWith (*) [4,3,2,1] [1,10,100,1000, ....])
==> sum [4 * 1, 3 * 10, 2 * 100, 1 * 1000]
==> 4 + 30 + 200 + 1000
==> 1234
However, this solution is slower than the ones with foldl
, due to the call to reverse
and since you're building up those powers of ten only to use them directly again. On the plus side, this way of building numbers is closer to the way people usually think (at least I do!), while the foldl
-solutions in essence use Horner's rule.