-
Notifications
You must be signed in to change notification settings - Fork 28
/
Person.hs
96 lines (76 loc) · 3.06 KB
/
Person.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
module Person where
import Control.Lens
import Data.List (isInfixOf)
import Data.Validation
newtype Name = Name { unName :: String } deriving Show
newtype Email = Email { unEmail :: String } deriving Show
newtype Age = Age { unAge :: Int } deriving Show
data Person = Person { name :: Name
, email :: Email
, age :: Age
} deriving Show
data Error = NameBetween1And50
| EmailMustContainAtChar
| AgeBetween0and120
deriving Show
-- Smart constructors
mkName :: String -> Validation [Error] Name
mkName s = let l = length s
in if l >= 1 && l <= 50
then _Success # Name s
else _Failure # [ NameBetween1And50 ]
mkEmail :: String -> Validation [Error] Email
mkEmail s = if "@" `isInfixOf` s
then _Success # Email s
else _Failure # [ EmailMustContainAtChar ]
mkAge :: Int -> Validation [Error] Age
mkAge a = if a >= 0 && a <= 120
then _Success # Age a
else _Failure # [ AgeBetween0and120 ]
mkPerson :: String -> String -> Int -> Validation [Error] Person
mkPerson pName pEmail pAge =
Person
<$> mkName pName
<*> mkEmail pEmail
<*> mkAge pAge
-- Examples
-- Data constructors for `Name`, `Age`, `Email`, and `Person` should not be
-- exported to the example code below:
validPerson :: Validation [Error] Person
validPerson = mkPerson "Bob" "bob@gmail.com" 25
-- Success (Person {name = Name {unName = "Bob"}, email = Email {unEmail = "bob@gmail.com"}, age = Age {unAge = 25}})
badName :: Validation [Error] Person
badName = mkPerson "" "bob@gmail.com" 25
-- Failure [NameBetween1And50]
badEmail :: Validation [Error] Person
badEmail = mkPerson "Bob" "bademail" 25
-- Failure [EmailMustContainAtChar]
badAge :: Validation [Error] Person
badAge = mkPerson "Bob" "bob@gmail.com" 150
-- Failure [AgeBetween0and120]
badEverything :: Validation [Error] Person
badEverything = mkPerson "" "bademail" 150
-- Failure [NameBetween1And50,EmailMustContainAtChar,AgeBetween0and120]
asMaybeGood :: Maybe Person
asMaybeGood = validPerson ^? _Success
-- Just (Person {name = Name {unName = "Bob"}, email = Email {unEmail = "bob@gmail.com"}, age = Age {unAge = 25}})
asMaybeBad :: Maybe Person
asMaybeBad = badEverything ^? _Success
-- Nothing
asEitherGood :: Either [Error] Person
asEitherGood = validPerson ^. _Either
-- Right (Person {name = Name {unName = "Bob"}, email = Email {unEmail = "bob@gmail.com"}, age = Age {unAge = 25}})
asEitherBad :: Either [Error] Person
asEitherBad = badEverything ^. _Either
-- Left [NameBetween1And50,EmailMustContainAtChar,AgeBetween0and120]
main :: IO ()
main = do
putStrLn $ "validPerson: " ++ show validPerson
putStrLn $ "badName: " ++ show badName
putStrLn $ "badEmail: " ++ show badEmail
putStrLn $ "badAge: " ++ show badAge
putStrLn $ "badEverything: " ++ show badEverything
putStrLn $ "asMaybeGood: " ++ show asMaybeGood
putStrLn $ "asMaybeBad: " ++ show asMaybeBad
putStrLn $ "asEitherGood: " ++ show asEitherGood
putStrLn $ "asEitherBad: " ++ show asEitherBad