Skip to content

Instantly share code, notes, and snippets.

@joker1007
Created October 16, 2012 13:10
Show Gist options
  • Save joker1007/3899179 to your computer and use it in GitHub Desktop.
Save joker1007/3899179 to your computer and use it in GitHub Desktop.
import Data.List
import Data.Char
import Control.Monad
import System.Environment
data Card = AMEX String | Discover String | MasterCard String | Visa String | Unknown deriving Show
detectCard :: String -> Card
detectCard cardNumber@(x:y:_)
| ("34" `isPrefixOf` cardNumber) || ("37" `isPrefixOf` cardNumber) = AMEX cardNumber
| "6011" `isPrefixOf` cardNumber = Discover cardNumber
| (x == '5') && (y `elem` map intToDigit [1..5]) = MasterCard cardNumber
| x == '4' = Visa cardNumber
validLength :: Card -> Bool
validLength (AMEX n) = length n == 15
validLength (Discover n) = length n == 16
validLength (MasterCard n) = length n == 16
validLength (Visa n) = length n == 13 || length n == 16
validLength Unknown = False
validLuhn :: Card -> Bool
validLuhn Unknown = False
validLuhn card = sum splitted_doubled `mod` 10 == 0
where num = case card of
AMEX s -> s
Discover s -> s
MasterCard s -> s
Visa s -> s
doubled = zipWith ($) (cycle [id, (* 2)]) $ map digitToInt $ reverse num
splitted_doubled = concatMap (map digitToInt . show) doubled
main :: IO ()
main = do s <- liftM (filter (/= ' ') . head) getArgs
let card = detectCard s
print $ validLength card && validLuhn card
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment