# Concatenate the square of all the digits of a number

Task: given a number (positive or negative), square every digit of it and concatenate them, forming a resulting number.

For example:

9119 should become 811181 = 9^2*10^0 + 1*10^1 + 1*10^2 + 9^2*10^3 (-1) should become (-1)

My code:

-- convert a number to the list of digits
-- doesn't work with negative numbers
digs :: Integral x => x -> [x]
digs 0 = [0]
digs x = let
helper :: Integral x => x -> [x]
helper 0 = []
helper n = helper (n div 10) ++ [n mod 10]
in
helper x

squareDigit :: Int -> Int
squareDigit n = let sign = signum n
digits = (digs (abs n))
digs_sq = map (^ 2) digits
-- we can't concat squares as they may have more then 1 digit
digs_sq_flat = map digs digs_sq >>= id
in
sign * foldl (\acc x -> x + (acc * 10)) 0 digs_sq_flat


Basically, it works:

*SquareDigit> squareDigit 9119
811181
*SquareDigit> squareDigit (-9119)
-811181


But maybe, my solution can be made more elegant.

Separate out combinators that apply some perspective to your data.

squareDigit = overAbs $overDigits$ concatMap \$ digs . (^ 2) where
overAbs f n = signum n * f (abs n)
overDigits f = foldl (\acc x -> x + (acc * 10)) 0 . f . digs


You could replace

digs_sq_flat = map digs digs_sq >>= id


with

digs_sq_flat = concatMap digs digs_sq


(>>= id) is the definition of join from Control.Monad, which, when specialized to [a] is the same thing as concat. So you basically have a map followed by concat which is exactly concatMap