# replace digit at some positions in number

I'm trying to write function, that replace digits at some positions in number.

For example f 91521 [3,4] -> [91001,91111,91221,91331,91441,91551,91661,91771,91881,91991]

It's behavior like 91**1 -> ..., so I named it as a 'whitemask'.

Question 1: is "whitemask" a normal and adequately name for that function?

After that I've formulated that 'whitemask' function.

sublists :: (Eq a) => [a] -> [[a]]
sublists list = [x | x <- subsequences list, x /= []]

numbers :: [Int]
numbers =  take 10 [0..]

numLength :: Integer -> Int
numLength = length . show

decreaseList :: Num a => [a] -> a -> [a]
decreaseList = (\a b c -> map (a c) b) (flip (-))

listToNum :: [Int] -> Integer
listToNum digits = toInteger $foldl1 (\x y -> x*10 + y) digits numToList :: Integer -> [Int] numToList x = map digitToInt$ show x

remove :: [Int] -> [Int] -> [[Int]]
remove [] x = [x]
remove (x:xs) list = putted : remove (decreaseList xs x) unputted
where [putted,unputted] = (\(x,y) -> [init x,y]) $splitAt x list sew :: [[a]] -> a -> [a] sew list sewer = foldr1 (\x y -> x ++ [sewer] ++ y) list whitemask :: Integer -> [Int] -> [Integer] whitemask num places = filter (\x -> numLength x == numLength num )$ map (listToNum . sew (remove places (numToList num))) numbers


But in context of all problem where that function might be used I figured out, that I need only fix-length answers. For examples, it works like

> whitemask 75148 [1,3,4]
[15118,25228,35338,45448,55558,65668,75778,85888,95998]


and answer isn't contain '5008' element.

Question 2: is that fix-length filtering 'whitemask' function's business? Or it would be better to return all possible variants and filtering them if it really needed?

When I've started to use that function in complicated iterates ways I figured out that it's might do some unnecessary and superfluous calculations.

Question 3: how can I refactor 'whitemask' function with less-usage folds maps and recursions?

Any cosmetics and style advices are appreciated.

ps: did I select the right place to asking for? (question could be migrated to SO actually)

UPD: I figured out that sew can be written much easier.

sew list sewer = concat $intersperse [sewer] list  ## 1 Answer I didn't thought about the algorithm itself, but shortened the code a little bit: decreaseList :: Num a => [a] -> a -> [a] decreaseList b c = map (subtract c) b listToNum :: [Int] -> Integer listToNum = toInteger . foldl1 ((+).(*10)) numToList :: Integer -> [Int] numToList = map digitToInt . show remove :: [Int] -> [Int] -> [[Int]] remove [] x = [x] remove (x:xs) list = let (putted, unputted) = splitAt x list in (init putted) : remove (decreaseList xs x) unputted sew :: [[a]] -> a -> [a] sew list sewer = foldr1 ((++).(++[sewer])) list whitemask :: Integer -> [Int] -> [Integer] whitemask num places = let list = map (listToNum . sew (remove places (numToList num))) [0..9] in filter (((==) on length . show) num) list  I think there is still room for improvement...  A shorter version: whitemask :: Integer -> [Int] -> [Integer] whitemask num places = map (listToNum . replace) [0..9] where replace digit = foldr ((:).findDigit) []$ zip (numToList num) [1..] where
findDigit (d,i) | i elem places = digit
| otherwise = d

listToNum :: [Int] -> Integer
listToNum = toInteger . foldl1 ((+).(*10))

numToList :: Integer -> [Int]
numToList = map digitToInt . show


A shorter version, with fixed-length filtering:

whitemask :: Integer -> [Int] -> [Integer]
whitemask num places = map replace digits  where
digits = if 1 elem places then [1..9] else [0..9]
toList = map digitToInt $show num replace digit = foldl toNum 0$ zip toList [1..] where
toNum r (d,i) = 10*r + (fromIntegral \$ if i elem places then digit else d)


I can't promise that I'll end up with a one-liner, though...