-
Notifications
You must be signed in to change notification settings - Fork 0
/
applicativeInstances.hs
102 lines (78 loc) · 2.44 KB
/
applicativeInstances.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
97
98
99
100
101
102
newtype Identity a = Identity a
deriving (Eq, Ord, Show)
instance Functor Identity where
fmap f (Identity x) = (Identity (f x))
instance Applicative Identity where
pure x = Identity x
(<*>) (Identity f) (Identity x) = (Identity (f x))
newtype Constant a b =
Constant { getConstant :: a }
deriving (Eq, Ord, Show)
instance Functor (Constant a) where
fmap f x = (Constant (getConstant x))
instance (Monoid a) => Applicative (Constant a) where
pure x = (Constant mempty)
(<*>) fc xc = (Constant (mappend (getConstant fc) (getConstant xc)))
validateLength :: Int -> String -> Maybe String
validateLength maxLen s =
if (length s) > maxLen
then Nothing
else Just s
newtype Name = Name String deriving (Eq, Show)
newtype Address = Address String deriving (Eq, Show)
mkName :: String -> Maybe Name
mkName s = fmap Name $ validateLength 25 s
mkAddress :: String -> Maybe Address
mkAddress a = fmap Address $ validateLength 100 a
data Person =
Person Name Address
deriving (Eq, Show)
mkPerson :: String -> String -> Maybe Person
mkPerson n a =
case mkName n of
Nothing -> Nothing
Just n' ->
case mkAddress a of
Nothing -> Nothing
Just a' ->
Just $ Person n' a'
data Cow = Cow {
name :: String
, age :: Int
, weight :: Int
} deriving (Eq, Show)
noEmpty :: String -> Maybe String
noEmpty "" = Nothing
noEmpty str = Just str
noNegative :: Int -> Maybe Int
noNegative n | n >= 0 = Just n
| otherwise = Nothing
cowFromString :: String -> Int -> Int -> Maybe Cow
cowFromString name' age' weight' = Cow <$> noEmpty name' <*> noNegative age' <*> noNegative weight'
-- Applicative laws:
--
-- Identity law -
-- Applying id embedded in structure itself is the identity function
--
-- pure id <*> x == x
--
-- Composition commutes with application -
-- Applying an application of composed functions is the same
-- as composing applications
--
-- pure (.) <*> u <*> v <*> w == u <*> (v <*> w)
--
-- Homomorphism -
-- Applying a function embedded in structure to a value embedded
-- in structure should be the same as embedding the result of passing
-- the value to the function into structure
--
-- In other words: structure embedding via pure should commute with application
--
-- pure f <*> pure x == pure (f x)
--
-- Interchange -
--
-- I'm not sure how to express this one as a paragraph, but the invariant is:
--
-- u <*> pure v == pure ($ v) <*> u