Created
April 12, 2016 07:42
-
-
Save vano468/a28b5fead1e3b2d5c28292b738057b4e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data Error = ParsingError | IncompleteDataError | IncorrectDataError String | |
deriving (Show, Eq) | |
data Person = Person { firstName :: String, lastName :: String, age :: Int } | |
deriving (Show, Eq) | |
parsePerson :: String -> Either Error Person | |
parsePerson = validatePerson . buildPerson (Right $ Person "" "" (-1)) . parse where | |
trim = unwords . words | |
parse = map (map trim . splitOn "=") . splitOn "\n" | |
isNumber = (== 0) . length . dropWhile isDigit | |
buildPerson result [] = result | |
buildPerson error@(Left _) _ = error | |
buildPerson (Right person) (x:xs) = buildPerson (addAttribute person x) xs | |
addAttribute person ("firstName":[value]) | |
= Right person { firstName = value } | |
addAttribute person ("lastName":[value]) | |
= Right person { lastName = value } | |
addAttribute person ("age":[value]) | |
| isNumber value = Right person { age = read value :: Int } | |
| otherwise = Left $ IncorrectDataError value | |
addAttribute person attribute | |
| length (filter (/= "") attribute) /= 2 = Left ParsingError | |
| otherwise = Right person | |
validatePerson person@(Right (Person fName lName age)) | |
| fName == "" || lName == "" || age == (-1) = Left IncompleteDataError | |
| otherwise = person | |
validatePerson error = error | |
parsePersonSpecs = [ | |
(1, "firstName = John\nlastName = Connor\nage = 30", Right (Person {firstName = "John", lastName = "Connor", age = 30})), | |
(2, "firstName = John Smith\nlastName = Connor\nage = 30\nasde=as11", Right (Person {firstName = "John Smith", lastName = "Connor", age = 30})), | |
(3, "firstName=Barbarian\nlastName=Conn On\nage=30", Right (Person {firstName = "Barbarian", lastName = "Conn On", age = 30})), | |
(4, "firstName=Barbarian\nlastName=Conn On\nage=30\ng dsfsd", Left ParsingError), | |
(5, "firstName=Barbarian\nlastName=Conn On\nage=30\ng dsfsd\n drrr", Left ParsingError), | |
(6, "firstName=Barbarian\nlastName=Conn On", Left IncompleteDataError), | |
(7, " firstName = John\nlastName = Connor\nage = 2f8 ", Left (IncorrectDataError "2f8")), | |
(8, "firstName = John Smith\nlastName = Connor\nage = 3d0\nasde=", Left ParsingError) | |
] | |
runSpecs [] _ = [] | |
runSpecs (x:xs) f = runSpec x : runSpecs xs f where | |
runSpec (id,input,expected) = (id, f input == expected) | |
runSpecById [] _ _ = Left "spec not found" | |
runSpecById ((specId,input,expected):xs) f id | |
| specId == id = Right $ (("expected",expected),("actual",f input),("passed", f input == expected)) | |
| otherwise = runSpecById xs f id | |
runParsePersonSpecs = runSpecs parsePersonSpecs parsePerson | |
runParsePersonSpec = runSpecById parsePersonSpecs parsePerson | |
parsePerson' = (buildPerson (Right $ Person "" "" 0)) . | |
(checkAttrsPresence ["firstName", "lastName", "age"] []) . | |
(validateData []) . parse where | |
trim = unwords . words | |
parse = map (filter (/= "") . map trim . splitOn "=") . splitOn "\n" | |
isNumber = (== 0) . length . dropWhile isDigit | |
validateData acc [] = Right acc | |
validateData acc (x:xs) | |
| length x /= 2 = Left ParsingError | |
| otherwise = validateData (x:acc) xs | |
checkAttrsPresence _ _ error@(Left _) = error | |
checkAttrsPresence attrs filtered (Right []) | |
| length attrs > 0 = Left IncompleteDataError | |
| otherwise = Right filtered | |
checkAttrsPresence attrs filtered (Right (x:xs)) | |
= checkAttrsPresence (filter (/= head x) attrs) | |
(x:filtered) (Right xs) | |
buildPerson _ _ = Right [1] | |
buildPerson error@(Left _) _ = error | |
buildPerson person (Right []) = person | |
buildPerson (Right person) (Right (x:xs)) | |
= buildPerson (addAttribute person x) (Right xs) | |
addAttribute person ("age":[value]) | |
| isNumber value = Right person { age = read value :: Int } | |
| otherwise = Left $ IncorrectDataError value | |
addAttribute person (attr:[value]) | |
| attr == "firstName" = Right person { firstName = value } | |
| attr == "lastName" = Right person { lastName = value } | |
| otherwise = Right person |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment