Haskell Quiz/Credit Cards/Solution Dolio
Revision as of 07:32, 28 April 2007
This solution does nothing particularly special. The constraints on each type of card are expressed as guards in some MonadPlus, which allows the results of those functions to be summed to get a result. The Luhn algorithm is fairly straight forward list processing.
The program expects command line arguments consisting only of the credit card number. The arguments are concatenated into a single string, so one can use as many or as few spaces to break it up as they wish.
import Control.Monad import Data.Char import Data.List import Data.Maybe import System.Environment luhn :: [Int] -> Bool luhn = (==0) . (`mod` 10) . sum . foldr split  . zipWith ($) (cycle [id, (*2)]) . reverse split n l | n > 9 = split d (m:l) | otherwise = n:l where (d, m) = divMod n 10 amex l@(x:y:_) = do guard $ length l == 15 guard $ x == 3 guard $ y `elem` [4, 7] return "AMEX" discover l = do guard $ length l == 16 guard $ [6,0,1,1] `isPrefixOf` l return "Discover" visa l@(x:_) = do guard $ length l `elem` [13, 16] guard $ x == 4 return "Visa" mastercard l@(x:y:_) = do guard $ length l == 16 guard $ x == 5 guard $ y `elem` [1..5] return "Mastercard" unknown l = return "Unknown" cardType l = fromJust . msum . map ($ l) $ [amex, discover, visa, mastercard, unknown] main = putStrLn . unwords . (\l -> [if luhn l then "Valid" else "Invalid", cardType l, "card"]) . map (digitToInt) . concat =<< getArgs </hasekll>