Skip to content

Instantly share code, notes, and snippets.

@groz
Last active November 15, 2016 22:03
Show Gist options
  • Save groz/2efeafc7078bec98c47dfd5c5d6256d4 to your computer and use it in GitHub Desktop.
Save groz/2efeafc7078bec98c47dfd5c5d6256d4 to your computer and use it in GitHub Desktop.
Luhn algorithm for credit card validation in Elm
import Html exposing (..)
import Html.Events exposing (..)
import Html.Attributes exposing (..)
-- UI part
main =
beginnerProgram { model = { creditCardNumber = "", isValid = False } , view = view, update = update }
type alias Model = { creditCardNumber: String, isValid: Bool }
type Msg = UpdateNumber String
update : Msg -> Model -> Model
update msg model =
case msg of
UpdateNumber num ->
{ model | creditCardNumber = num, isValid = num |> validate }
view : Model -> Html Msg
view model =
div []
[ input [onInput UpdateNumber, placeholder "Enter credit card..."] []
, text (if model.isValid then " √" else " X")
]
-- Algorithmic part
validate : String -> Bool
validate ccNumber =
let
len = String.length ccNumber
getSum digits = digits |> transform |> List.sum
validateSum sum = sum % 10 == 0
in
len > 12 && len < 20 && (
ccNumber
|> toDigits
|> Result.map (getSum >> validateSum)
|> Result.withDefault False
)
toDigits : String -> Result String (List Int)
toDigits str =
str
|> String.toList
|> List.map (String.fromChar >> String.toInt)
|> List.foldr (Result.map2 (::)) (Result.Ok [])
transform : List Int -> List Int
transform digits =
let
flatten number =
if number > 9 then number - 9 else number
doubleOdd idx digit =
if idx % 2 /= 0 then flatten (digit * 2) else digit
in
digits
|> List.reverse
|> List.indexedMap doubleOdd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment