Skip to content

Commit 199cf70

Browse files
committed
Complete Set16
1 parent a1c9804 commit 199cf70

File tree

2 files changed

+41
-18
lines changed

2 files changed

+41
-18
lines changed

Set16a.hs

+12-8
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import Data.List
1818
-- +++ OK, passed 1 test.
1919

2020
isSorted :: (Show a, Ord a) => [a] -> Property
21-
isSorted = todo
21+
isSorted xs = sort xs === xs
2222

2323
------------------------------------------------------------------------------
2424
-- Ex 2: In this and the following exercises, we'll build a suite of
@@ -50,7 +50,7 @@ isSorted = todo
5050
-- +++ OK, passed 1 test.
5151

5252
sumIsLength :: Show a => [a] -> [(a,Int)] -> Property
53-
sumIsLength input output = todo
53+
sumIsLength input output = length input === sum (map snd output)
5454

5555
-- This is a function that passes the sumIsLength test but is wrong
5656
freq1 :: Eq a => [a] -> [(a,Int)]
@@ -79,7 +79,7 @@ freq1 (x:y:xs) = [(x,1),(y,length xs + 1)]
7979
-- +++ OK, passed 100 tests.
8080

8181
inputInOutput :: (Show a, Eq a) => [a] -> [(a,Int)] -> Property
82-
inputInOutput input output = todo
82+
inputInOutput input output = forAll (elements input) (\x -> x `elem` map fst output)
8383

8484
-- This function passes both the sumIsLength and inputInOutput tests
8585
freq2 :: Eq a => [a] -> [(a,Int)]
@@ -110,7 +110,7 @@ freq2 xs = map (\x -> (x,1)) xs
110110
-- +++ OK, passed 100 tests.
111111

112112
outputInInput :: (Show a, Eq a) => [a] -> [(a,Int)] -> Property
113-
outputInInput input output = todo
113+
outputInInput input output = forAll (elements output) (\(x,n) -> n === length (filter (==x) input))
114114

115115
-- This function passes the outputInInput test but not the others
116116
freq3 :: Eq a => [a] -> [(a,Int)]
@@ -139,7 +139,8 @@ freq3 (x:xs) = [(x,1 + length (filter (==x) xs))]
139139
-- +++ OK, passed 100 tests.
140140

141141
frequenciesProp :: ([Char] -> [(Char,Int)]) -> NonEmptyList Char -> Property
142-
frequenciesProp freq input = todo
142+
frequenciesProp freq input = conjoin $ map ($ freq xs) [sumIsLength xs, inputInOutput xs, outputInInput xs]
143+
where xs = getNonEmpty input
143144

144145
frequencies :: Eq a => [a] -> [(a,Int)]
145146
frequencies [] = []
@@ -170,7 +171,10 @@ frequencies (x:ys) = (x, length xs) : frequencies others
170171
-- [2,4,10]
171172

172173
genList :: Gen [Int]
173-
genList = todo
174+
genList = do
175+
n <- choose (3,5)
176+
xs <- vectorOf n (choose (0,10))
177+
return $ sort xs
174178

175179
------------------------------------------------------------------------------
176180
-- Ex 7: Here are the datatypes Arg and Expression from Set 15. Write
@@ -208,7 +212,7 @@ data Expression = Plus Arg Arg | Minus Arg Arg
208212
deriving (Show, Eq)
209213

210214
instance Arbitrary Arg where
211-
arbitrary = todo
215+
arbitrary = oneof [Number <$> choose (0,10), Variable <$> elements "abcxyz"]
212216

213217
instance Arbitrary Expression where
214-
arbitrary = todo
218+
arbitrary = oneof [Plus <$> arbitrary <*> arbitrary, Minus <$> arbitrary <*> arbitrary]

Set16b.hs

+29-10
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ import Data.Char (toUpper)
1010
-- 3. The type Money is imported from Example.Phantom but you'll need
1111
-- to introduce GBP yourself.
1212

13-
pounds = todo
13+
data GBP
14+
15+
pounds :: Money GBP
16+
pounds = Money 3
1417

1518
------------------------------------------------------------------------------
1619
-- Ex 2: Implement composition for Rates. Give composeRates a
@@ -27,7 +30,8 @@ pounds = todo
2730
usdToChf :: Rate USD CHF
2831
usdToChf = Rate 1.11
2932

30-
composeRates rate1 rate2 = todo
33+
composeRates :: Rate from to -> Rate to to' -> Rate from to'
34+
composeRates (Rate r1) (Rate r2) = Rate (r1 * r2)
3135

3236
------------------------------------------------------------------------------
3337
-- Ex 3: Tracking first, last and full names with phantom types. The
@@ -47,18 +51,23 @@ composeRates rate1 rate2 = todo
4751
-- toFirst "bob" :: Name First
4852
-- toLast "smith" :: Name Last
4953

54+
data First
55+
data Last
56+
data Full
57+
58+
data Name a = Name String
5059

5160
-- Get the String contained in a name
52-
--fromName :: Name a -> String
53-
fromName = todo
61+
fromName :: Name a -> String
62+
fromName (Name a) = a
5463

5564
-- Build a Name First
56-
--toFirst :: String -> Name First
57-
toFirst = todo
65+
toFirst :: String -> Name First
66+
toFirst s = Name s
5867

5968
-- Build a Name Last
60-
--toLast :: String -> Name Last
61-
toLast = todo
69+
toLast :: String -> Name Last
70+
toLast s = Name s
6271

6372
------------------------------------------------------------------------------
6473
-- Ex 4: Implement the functions capitalize and toFull.
@@ -78,9 +87,11 @@ toLast = todo
7887
-- capitalize (toLast "smith") :: Name Last
7988
-- fromName (capitalize (toLast "smith")) ==> "Smith"
8089

81-
capitalize = todo
90+
capitalize :: Name a -> Name a
91+
capitalize (Name a) = Name (toUpper (head a) : tail a)
8292

83-
toFull = todo
93+
toFull :: Name First -> Name Last -> Name Full
94+
toFull (Name first) (Name last) = Name (first ++ " " ++ last)
8495

8596
------------------------------------------------------------------------------
8697
-- Ex 5: Type classes can let you write code that handles different
@@ -94,3 +105,11 @@ toFull = todo
94105
class Render currency where
95106
render :: Money currency -> String
96107

108+
instance Render EUR where
109+
render (Money a) = show a ++ "e"
110+
111+
instance Render USD where
112+
render (Money a) = "$" ++ show a
113+
114+
instance Render CHF where
115+
render (Money a) = show a ++ "chf"

0 commit comments

Comments
 (0)