Skip to content

Commit ca5323a

Browse files
committed
feat: Progress with Ch15 exercises, nearly done
1 parent 0b9b156 commit ca5323a

File tree

5 files changed

+86
-72
lines changed

5 files changed

+86
-72
lines changed

hffp.cabal

+7-7
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,24 @@ extra-source-files:
1616

1717
library
1818
exposed-modules:
19-
Ch14.Addition
20-
Ch14.Morse
21-
Ch8.Playground
22-
Ch11.Cipher
23-
Ch9.Cipher
24-
other-modules:
2519
Ch10.Playground
20+
Ch11.Cipher
2621
Ch11.HuttonsRazor
2722
Ch11.Phone
2823
Ch11.PhoneAlt
2924
Ch11.Playground
3025
Ch12.Playground
3126
Ch13.Person
3227
Ch13.Playground
28+
Ch14.Addition
29+
Ch14.Morse
3330
Ch15.Bull
31+
Ch15.Exercise
3432
Ch15.Listy
3533
Ch15.ListyInstances
3634
Ch15.Playground
37-
Ch15.Semigroups
35+
Ch8.Playground
36+
Ch9.Cipher
3837
Ch9.Playground
3938
Ch9.StdFunc
4039
Lib
@@ -78,6 +77,7 @@ test-suite hffp-test
7877
Ch14.Identity
7978
Ch14.MorseSpec
8079
Ch14.Trivial
80+
Ch15.ExerciseSpec
8181
Ch8.WordNumberSpec
8282
hs-source-dirs:
8383
test

package.yaml

-6
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,6 @@ library:
4242
- containers
4343
- hspec
4444
- QuickCheck
45-
exposed-modules:
46-
- Ch14.Addition
47-
- Ch14.Morse
48-
- Ch8.Playground
49-
- Ch11.Cipher
50-
- Ch9.Cipher
5145

5246
executables:
5347
hffp:
+22-58
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
module Ch15.Semigroups where
1+
module Ch15.Exercise where
22

33
import Test.QuickCheck hiding (Failure, Success)
44

@@ -10,17 +10,20 @@ data Trivial = Trivial
1010
instance Semigroup Trivial where
1111
_ <> _ = Trivial
1212

13+
instance Monoid Trivial where
14+
mempty = Trivial
15+
1316
instance Arbitrary Trivial where
1417
arbitrary = pure Trivial
1518

16-
semigroupAssocProp :: (Eq a, Semigroup a) => a -> a -> a -> Bool
17-
semigroupAssocProp a b c = a <> (b <> c) == (a <> b) <> c
18-
1919
newtype Identity a = Identity a deriving (Eq, Show)
2020

2121
instance (Semigroup a) => Semigroup (Identity a) where
2222
(Identity a) <> (Identity b) = Identity $ a <> b
2323

24+
instance (Monoid a) => Monoid (Identity a) where
25+
mempty = Identity mempty
26+
2427
instance (Arbitrary a) => Arbitrary (Identity a) where
2528
arbitrary = Identity <$> arbitrary
2629

@@ -29,6 +32,9 @@ data Two a b = Two a b deriving (Eq, Show)
2932
instance (Semigroup a, Semigroup b) => Semigroup (Two a b) where
3033
(Two a b) <> (Two a' b') = Two (a <> a') (b <> b')
3134

35+
instance (Monoid a, Monoid b) => Monoid (Two a b) where
36+
mempty = Two mempty mempty
37+
3238
instance (Arbitrary a, Arbitrary b) => Arbitrary (Two a b) where
3339
arbitrary = Two <$> arbitrary <*> arbitrary
3440

@@ -37,6 +43,9 @@ data Three a b c = Three a b c deriving (Eq, Show)
3743
instance (Semigroup a, Semigroup b, Semigroup c) => Semigroup (Three a b c) where
3844
(Three a b c) <> (Three a' b' c') = Three (a <> a') (b <> b') (c <> c')
3945

46+
instance (Monoid a, Monoid b, Monoid c) => Monoid (Three a b c) where
47+
mempty = Three mempty mempty mempty
48+
4049
instance (Arbitrary a, Arbitrary b, Arbitrary c) => Arbitrary (Three a b c) where
4150
arbitrary = Three <$> arbitrary <*> arbitrary <*> arbitrary
4251

@@ -45,6 +54,9 @@ data Four a b c d = Four a b c d deriving (Eq, Show)
4554
instance (Semigroup a, Semigroup b, Semigroup c, Semigroup d) => Semigroup (Four a b c d) where
4655
(Four a b c d) <> (Four a' b' c' d') = Four (a <> a') (b <> b') (c <> c') (d <> d')
4756

57+
instance (Monoid a, Monoid b, Monoid c, Monoid d) => Monoid (Four a b c d) where
58+
mempty = Four mempty mempty mempty mempty
59+
4860
instance (Arbitrary a, Arbitrary b, Arbitrary c, Arbitrary d) => Arbitrary (Four a b c d) where
4961
arbitrary = Four <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
5062

@@ -53,6 +65,9 @@ newtype BoolConj = BoolConj Bool deriving (Eq, Show)
5365
instance Semigroup BoolConj where
5466
(BoolConj b) <> (BoolConj b') = BoolConj $ b && b'
5567

68+
instance Monoid BoolConj where
69+
mempty = BoolConj $ getAll (mempty :: All)
70+
5671
instance Arbitrary BoolConj where
5772
arbitrary = BoolConj <$> arbitrary
5873

@@ -61,6 +76,9 @@ newtype BoolDisj = BoolDisj Bool deriving (Eq, Show)
6176
instance Semigroup BoolDisj where
6277
(BoolDisj b) <> (BoolDisj b') = BoolDisj $ b || b'
6378

79+
instance Monoid BoolDisj where
80+
mempty = BoolDisj $ getAny (mempty :: Any)
81+
6482
instance Arbitrary BoolDisj where
6583
arbitrary = BoolDisj <$> arbitrary
6684

@@ -88,9 +106,6 @@ instance (CoArbitrary a, Arbitrary b) => Arbitrary (Combine a b) where
88106
instance Show (Combine a b) where
89107
show _ = "Combine (a -> b)"
90108

91-
combineSemigroupAssocProp :: (Eq b, Semigroup b) => Combine a b -> Combine a b -> Combine a b -> a -> Bool
92-
combineSemigroupAssocProp f g h a = unCombine (f <> (g <> h)) a == unCombine ((f <> g) <> h) a
93-
94109
newtype Comp a = Comp {unComp :: a -> a}
95110

96111
instance (Semigroup a) => Semigroup (Comp a) where
@@ -102,9 +117,6 @@ instance (CoArbitrary a, Arbitrary a) => Arbitrary (Comp a) where
102117
instance Show (Comp a) where
103118
show _ = "Comp (a -> a)"
104119

105-
compSemigroupAssocProp :: (Eq a, Semigroup a) => Comp a -> Comp a -> Comp a -> a -> Bool
106-
compSemigroupAssocProp f g h a = unComp (f <> (g <> h)) a == unComp ((f <> g) <> h) a
107-
108120
data Validation a b = Failure a | Success b deriving (Eq, Show)
109121

110122
instance (Semigroup a) => Semigroup (Validation a b) where
@@ -124,51 +136,3 @@ failure = Failure
124136

125137
success :: Int -> Validation String Int
126138
success = Success
127-
128-
-- Move this to the test directory
129-
main :: IO ()
130-
main = do
131-
putStr "Trivial Semigroup Assoc Prop: "
132-
quickCheck (semigroupAssocProp @Trivial)
133-
134-
putStr "Identity a Assoc Prop: "
135-
quickCheck (semigroupAssocProp @(Identity (Sum Int)))
136-
137-
putStr "Identity a 2 Assoc Prop: "
138-
quickCheck (semigroupAssocProp @(Identity (Product Int)))
139-
140-
putStr "Identity a 3 Assoc Prop: "
141-
quickCheck (semigroupAssocProp @(Identity (First (Maybe Int))))
142-
143-
putStr "Two Assoc Prop: "
144-
quickCheck (semigroupAssocProp @(Two (Sum Int) String))
145-
146-
putStr "Two Assoc Prop: "
147-
quickCheck (semigroupAssocProp @(Two (Sum Int) (Product Int)))
148-
149-
putStr "Three Assoc Prop: "
150-
quickCheck (semigroupAssocProp @(Three Any (Sum Int) (Product Int)))
151-
152-
putStr "Four Assoc Prop: "
153-
quickCheck (semigroupAssocProp @(Four (First (Maybe String)) (Last (Maybe Bool)) All (Product Int)))
154-
155-
putStr "BoolConj Assoc Prop: "
156-
quickCheck (semigroupAssocProp @BoolConj)
157-
158-
putStr "BoolDisj Assoc Prop: "
159-
quickCheck (semigroupAssocProp @BoolDisj)
160-
161-
putStr "Or Assoc Prop: "
162-
quickCheck (semigroupAssocProp @(Or Int String))
163-
164-
putStr "Combine Assoc Prop: "
165-
quickCheck (combineSemigroupAssocProp @(Sum Int) @Int)
166-
167-
putStr "Comp Assoc Prop: "
168-
quickCheck (compSemigroupAssocProp @(Sum Int))
169-
170-
putStrLn ""
171-
print $ success 1 <> failure "blah"
172-
print $ failure "woot" <> failure "blah"
173-
print $ success 1 <> success 2
174-
print $ failure "woot" <> success 2

src/Ch15/Exercises.md

-1
This file was deleted.

test/Ch15/ExerciseSpec.hs

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
module Ch15.ExerciseSpec where
2+
3+
import Ch15.Exercise
4+
import Ch15.Playground
5+
6+
import Test.Hspec
7+
import Test.Hspec.QuickCheck
8+
9+
import Data.Monoid
10+
11+
semigroupAssocProp :: (Eq a, Semigroup a) => a -> a -> a -> Bool
12+
semigroupAssocProp a b c = a <> (b <> c) == (a <> b) <> c
13+
14+
compSemigroupAssocProp :: (Eq a, Semigroup a) => Comp a -> Comp a -> Comp a -> a -> Bool
15+
compSemigroupAssocProp f g h a = unComp (f <> (g <> h)) a == unComp ((f <> g) <> h) a
16+
17+
combineSemigroupAssocProp :: (Eq b, Semigroup b) => Combine a b -> Combine a b -> Combine a b -> a -> Bool
18+
combineSemigroupAssocProp f g h a = unCombine (f <> (g <> h)) a == unCombine ((f <> g) <> h) a
19+
20+
monoidLawsProp :: (Eq m, Monoid m) => m -> m -> m -> Bool
21+
monoidLawsProp a b c = semigroupAssocProp a b c && monoidLeftIdentityProp a && monoidRightIdentityProp a
22+
23+
spec :: Spec
24+
spec = do
25+
describe "Semigroup Assoc prop tests for datatypes" $ do
26+
prop "Trivial" $ semigroupAssocProp @Trivial
27+
prop "Identity a" $ semigroupAssocProp @(Identity (Sum Int))
28+
prop "Identity a (2)" $ semigroupAssocProp @(Identity (Product Int))
29+
prop "Identity a (3)" $ semigroupAssocProp @(Identity (First (Maybe Int)))
30+
prop "Two a b" $ semigroupAssocProp @(Two (Sum Int) String)
31+
prop "Two a b (2)" $ semigroupAssocProp @(Two (Sum Int) (Product Int))
32+
prop "Three a b c" $ semigroupAssocProp @(Three Any (Sum Int) (Product Int))
33+
prop "Four a b c d" $ semigroupAssocProp @(Four (First (Maybe String)) (Last (Maybe Bool)) All (Product Int))
34+
prop "BoolConj" $ semigroupAssocProp @BoolConj
35+
prop "BoolDisj" $ semigroupAssocProp @BoolDisj
36+
prop "Or a b" $ semigroupAssocProp @(Or Int String)
37+
prop "Combine a b" $ combineSemigroupAssocProp @(Sum Int) @Int
38+
prop "Comp a" $ compSemigroupAssocProp @(Sum Int)
39+
40+
it "Validation a" $
41+
and
42+
[ success 1 <> failure "blah" == Success 1
43+
, failure "woot" <> failure "blah" == Failure "wootblah"
44+
, success 1 <> success 2 == Success 1
45+
, failure "woot" <> success 2 == Success 2
46+
]
47+
describe "Monoid Laws tests for datatypes" $ do
48+
prop "Trivial" $ monoidLawsProp @Trivial
49+
prop "Identity a" $ monoidLawsProp @(Identity (Sum Int))
50+
prop "Identity a (2)" $ monoidLawsProp @(Identity (Product Int))
51+
prop "Identity a (3)" $ monoidLawsProp @(Identity (First (Maybe Int)))
52+
prop "Two a b" $ monoidLawsProp @(Two (Sum Int) String)
53+
prop "Two a b (2)" $ monoidLawsProp @(Two (Sum Int) (Product Int))
54+
prop "Three a b c" $ monoidLawsProp @(Three Any (Sum Int) (Product Int))
55+
prop "Four a b c d" $ monoidLawsProp @(Four (First (Maybe String)) (Last (Maybe Bool)) All (Product Int))
56+
prop "BoolConj" $ monoidLawsProp @BoolConj
57+
prop "BoolDisj" $ monoidLawsProp @BoolDisj

0 commit comments

Comments
 (0)