I am new to Haskell, and wrote a script to verify credit number.I did some tests, the script worked, but can it be improved further?isCreditCardNumber :: String -> BoolisCreditCardNumber number =    0 == creditCardReminder ( creditCardDouble ( blowupCreditCardNumber ( reverse number)))blowupCreditCardNumber :: String -> [(Int,Char)]blowupCreditCardNumber creditCardNumber = zip [1..] creditCardNumbercreditCardDouble :: [(Int,Char)] -> [Int]creditCardDouble [] = []creditCardDouble ((index,digit):rest)    | even index = (numberDoubleToList ((*2) $ digitToInt digit)) ++ creditCardDouble rest    | otherwise = digitToInt digit : creditCardDouble restnumberDoubleToList:: Int -> [Int]numberDoubleToList number    | number > 9 = map digitToInt (show number)    | otherwise  = [number]creditCardReminder :: [Int] -> IntcreditCardReminder xs = sum xs `mod` 10
Haskell code to verify credit number
beginner;haskell;checksum
You can eta-reduce blowupCreditCardNumber:blowupCreditCardNumber = zip [1..]Using composition, you can also make isCreditCardNumber pointfree:isCreditCardNumber = (==0) . creditCardReminder . creditCardDouble . blowupCreditCardNumber . reverseYou don't need to optimize numberDoubleToList by special-casing the one-digit case.numberDoubleToList = map digitToInt . showThe explicit recursion in creditCardDouble can be averted by using library functions that specialize in particular recursive patterns:creditCardDouble = concatMap foo where  foo (index, digit) | even index = numberDoubleToList $ (*2) $ digitToInt digit                     | otherwise = [digitToInt digit]foo's name makes foo look like a crutch, and that is good, because it is one.I would inline definitions that are only used once and do not deserve to be in a library:isCreditCardNumber = (==0) . (`mod` 10) . sum . concatMap foo . zip [1..] . reverse where  foo (index, digit) | even index = map digitToInt $ show $ (*2) $ digitToInt digit                     | otherwise = [digitToInt digit]digitToInt digit is used in both cases of foo, and so can be factored out:isCreditCardNumber = (==0) . (`mod` 10) . sum . concatMap foo . zip [1..] . reverse where  foo (index, digit) = bar index $ digitToInt digit  bar index | even index = map digitToInt . show  . (*2)            | otherwise = pureIn fact, we don't need to generate the index and pass it to foo if all we do with it is put it into bar later:isCreditCardNumber = (==0) . (`mod` 10) . sum . concatMap foo . zip (cycle [pure, map digitToInt . show . (*2)]) . reverse where  foo (doubler, digit) = doubler $ digitToInt digitfoo is almost trivial, lets get rid of it entirely:isCreditCardNumber = (==0) . (`mod` 10) . sum . concat . zipWith ($) (cycle [pure, map digitToInt . show . (*2)]) . map digitToInt . reversemap digitToInt . show is pure on single digits, so we can factor it out of that list and then even factor out the (*):isCreditCardNumber = (==0) . (`mod` 10) . sum . concatMap (map digitToInt . show) . zipWith (*) (cycle [1, 2]) . map digitToInt . reverseNote that if you know the parity of the length of the credit card number, you can get rid of the reverse.